xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
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"
22e8d8bef9SDimitry Andric using namespace llvm;
23e8d8bef9SDimitry Andric 
24e8d8bef9SDimitry Andric static std::pair<Type *, Align> getArgumentTypeAlign(const Argument &Arg,
25e8d8bef9SDimitry Andric                                                      const DataLayout &DL) {
26e8d8bef9SDimitry Andric   Type *Ty = Arg.getType();
27e8d8bef9SDimitry Andric   MaybeAlign ArgAlign;
28e8d8bef9SDimitry Andric   if (Arg.hasByRefAttr()) {
29e8d8bef9SDimitry Andric     Ty = Arg.getParamByRefType();
30e8d8bef9SDimitry Andric     ArgAlign = Arg.getParamAlign();
31e8d8bef9SDimitry Andric   }
32e8d8bef9SDimitry Andric 
33e8d8bef9SDimitry Andric   if (!ArgAlign)
34e8d8bef9SDimitry Andric     ArgAlign = DL.getABITypeAlign(Ty);
35e8d8bef9SDimitry Andric 
36bdd1243dSDimitry Andric   return std::pair(Ty, *ArgAlign);
37e8d8bef9SDimitry Andric }
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric namespace llvm {
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric static cl::opt<bool> DumpHSAMetadata(
420b57cec5SDimitry Andric     "amdgpu-dump-hsa-metadata",
430b57cec5SDimitry Andric     cl::desc("Dump AMDGPU HSA Metadata"));
440b57cec5SDimitry Andric static cl::opt<bool> VerifyHSAMetadata(
450b57cec5SDimitry Andric     "amdgpu-verify-hsa-metadata",
460b57cec5SDimitry Andric     cl::desc("Verify AMDGPU HSA Metadata"));
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric namespace AMDGPU {
490b57cec5SDimitry Andric namespace HSAMD {
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
525f757f3fSDimitry Andric // HSAMetadataStreamerV4
530b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
545f757f3fSDimitry Andric 
555f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::dump(StringRef HSAMetadataString) const {
560b57cec5SDimitry Andric   errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric 
595f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::verify(StringRef HSAMetadataString) const {
600b57cec5SDimitry Andric   errs() << "AMDGPU HSA Metadata Parser Test: ";
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   msgpack::Document FromHSAMetadataString;
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   if (!FromHSAMetadataString.fromYAML(HSAMetadataString)) {
650b57cec5SDimitry Andric     errs() << "FAIL\n";
660b57cec5SDimitry Andric     return;
670b57cec5SDimitry Andric   }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   std::string ToHSAMetadataString;
700b57cec5SDimitry Andric   raw_string_ostream StrOS(ToHSAMetadataString);
710b57cec5SDimitry Andric   FromHSAMetadataString.toYAML(StrOS);
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   errs() << (HSAMetadataString == StrOS.str() ? "PASS" : "FAIL") << '\n';
740b57cec5SDimitry Andric   if (HSAMetadataString != ToHSAMetadataString) {
750b57cec5SDimitry Andric     errs() << "Original input: " << HSAMetadataString << '\n'
760b57cec5SDimitry Andric            << "Produced output: " << StrOS.str() << '\n';
770b57cec5SDimitry Andric   }
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric 
80bdd1243dSDimitry Andric std::optional<StringRef>
815f757f3fSDimitry Andric MetadataStreamerMsgPackV4::getAccessQualifier(StringRef AccQual) const {
82bdd1243dSDimitry Andric   return StringSwitch<std::optional<StringRef>>(AccQual)
830b57cec5SDimitry Andric       .Case("read_only", StringRef("read_only"))
840b57cec5SDimitry Andric       .Case("write_only", StringRef("write_only"))
850b57cec5SDimitry Andric       .Case("read_write", StringRef("read_write"))
86bdd1243dSDimitry Andric       .Default(std::nullopt);
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric 
895f757f3fSDimitry Andric std::optional<StringRef> MetadataStreamerMsgPackV4::getAddressSpaceQualifier(
90bdd1243dSDimitry Andric     unsigned AddressSpace) const {
910b57cec5SDimitry Andric   switch (AddressSpace) {
920b57cec5SDimitry Andric   case AMDGPUAS::PRIVATE_ADDRESS:
930b57cec5SDimitry Andric     return StringRef("private");
940b57cec5SDimitry Andric   case AMDGPUAS::GLOBAL_ADDRESS:
950b57cec5SDimitry Andric     return StringRef("global");
960b57cec5SDimitry Andric   case AMDGPUAS::CONSTANT_ADDRESS:
970b57cec5SDimitry Andric     return StringRef("constant");
980b57cec5SDimitry Andric   case AMDGPUAS::LOCAL_ADDRESS:
990b57cec5SDimitry Andric     return StringRef("local");
1000b57cec5SDimitry Andric   case AMDGPUAS::FLAT_ADDRESS:
1010b57cec5SDimitry Andric     return StringRef("generic");
1020b57cec5SDimitry Andric   case AMDGPUAS::REGION_ADDRESS:
1030b57cec5SDimitry Andric     return StringRef("region");
1040b57cec5SDimitry Andric   default:
105bdd1243dSDimitry Andric     return std::nullopt;
1060b57cec5SDimitry Andric   }
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric 
109bdd1243dSDimitry Andric StringRef
1105f757f3fSDimitry Andric MetadataStreamerMsgPackV4::getValueKind(Type *Ty, StringRef TypeQual,
1110b57cec5SDimitry Andric                                         StringRef BaseTypeName) const {
112349cc55cSDimitry Andric   if (TypeQual.contains("pipe"))
1130b57cec5SDimitry Andric     return "pipe";
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   return StringSwitch<StringRef>(BaseTypeName)
1160b57cec5SDimitry Andric       .Case("image1d_t", "image")
1170b57cec5SDimitry Andric       .Case("image1d_array_t", "image")
1180b57cec5SDimitry Andric       .Case("image1d_buffer_t", "image")
1190b57cec5SDimitry Andric       .Case("image2d_t", "image")
1200b57cec5SDimitry Andric       .Case("image2d_array_t", "image")
1210b57cec5SDimitry Andric       .Case("image2d_array_depth_t", "image")
1220b57cec5SDimitry Andric       .Case("image2d_array_msaa_t", "image")
1230b57cec5SDimitry Andric       .Case("image2d_array_msaa_depth_t", "image")
1240b57cec5SDimitry Andric       .Case("image2d_depth_t", "image")
1250b57cec5SDimitry Andric       .Case("image2d_msaa_t", "image")
1260b57cec5SDimitry Andric       .Case("image2d_msaa_depth_t", "image")
1270b57cec5SDimitry Andric       .Case("image3d_t", "image")
1280b57cec5SDimitry Andric       .Case("sampler_t", "sampler")
1290b57cec5SDimitry Andric       .Case("queue_t", "queue")
1300b57cec5SDimitry Andric       .Default(isa<PointerType>(Ty)
1310b57cec5SDimitry Andric                    ? (Ty->getPointerAddressSpace() == AMDGPUAS::LOCAL_ADDRESS
1320b57cec5SDimitry Andric                           ? "dynamic_shared_pointer"
1330b57cec5SDimitry Andric                           : "global_buffer")
1340b57cec5SDimitry Andric                    : "by_value");
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric 
1375f757f3fSDimitry Andric std::string MetadataStreamerMsgPackV4::getTypeName(Type *Ty,
138bdd1243dSDimitry Andric                                                    bool Signed) const {
1390b57cec5SDimitry Andric   switch (Ty->getTypeID()) {
1400b57cec5SDimitry Andric   case Type::IntegerTyID: {
1410b57cec5SDimitry Andric     if (!Signed)
1420b57cec5SDimitry Andric       return (Twine('u') + getTypeName(Ty, true)).str();
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric     auto BitWidth = Ty->getIntegerBitWidth();
1450b57cec5SDimitry Andric     switch (BitWidth) {
1460b57cec5SDimitry Andric     case 8:
1470b57cec5SDimitry Andric       return "char";
1480b57cec5SDimitry Andric     case 16:
1490b57cec5SDimitry Andric       return "short";
1500b57cec5SDimitry Andric     case 32:
1510b57cec5SDimitry Andric       return "int";
1520b57cec5SDimitry Andric     case 64:
1530b57cec5SDimitry Andric       return "long";
1540b57cec5SDimitry Andric     default:
1550b57cec5SDimitry Andric       return (Twine('i') + Twine(BitWidth)).str();
1560b57cec5SDimitry Andric     }
1570b57cec5SDimitry Andric   }
1580b57cec5SDimitry Andric   case Type::HalfTyID:
1590b57cec5SDimitry Andric     return "half";
1600b57cec5SDimitry Andric   case Type::FloatTyID:
1610b57cec5SDimitry Andric     return "float";
1620b57cec5SDimitry Andric   case Type::DoubleTyID:
1630b57cec5SDimitry Andric     return "double";
1645ffd83dbSDimitry Andric   case Type::FixedVectorTyID: {
1655ffd83dbSDimitry Andric     auto VecTy = cast<FixedVectorType>(Ty);
1660b57cec5SDimitry Andric     auto ElTy = VecTy->getElementType();
1675ffd83dbSDimitry Andric     auto NumElements = VecTy->getNumElements();
1680b57cec5SDimitry Andric     return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric   default:
1710b57cec5SDimitry Andric     return "unknown";
1720b57cec5SDimitry Andric   }
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric msgpack::ArrayDocNode
1765f757f3fSDimitry Andric MetadataStreamerMsgPackV4::getWorkGroupDimensions(MDNode *Node) const {
1770b57cec5SDimitry Andric   auto Dims = HSAMetadataDoc->getArrayNode();
1780b57cec5SDimitry Andric   if (Node->getNumOperands() != 3)
1790b57cec5SDimitry Andric     return Dims;
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   for (auto &Op : Node->operands())
1820b57cec5SDimitry Andric     Dims.push_back(Dims.getDocument()->getNode(
1830b57cec5SDimitry Andric         uint64_t(mdconst::extract<ConstantInt>(Op)->getZExtValue())));
1840b57cec5SDimitry Andric   return Dims;
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric 
1875f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitVersion() {
1880b57cec5SDimitry Andric   auto Version = HSAMetadataDoc->getArrayNode();
1895f757f3fSDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMajorV4));
1905f757f3fSDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMinorV4));
1910b57cec5SDimitry Andric   getRootMetadata("amdhsa.version") = Version;
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric 
1945f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitTargetID(
1955f757f3fSDimitry Andric     const IsaInfo::AMDGPUTargetID &TargetID) {
1965f757f3fSDimitry Andric   getRootMetadata("amdhsa.target") =
1975f757f3fSDimitry Andric       HSAMetadataDoc->getNode(TargetID.toString(), /*Copy=*/true);
1985f757f3fSDimitry Andric }
1995f757f3fSDimitry Andric 
2005f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitPrintf(const Module &Mod) {
2010b57cec5SDimitry Andric   auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
2020b57cec5SDimitry Andric   if (!Node)
2030b57cec5SDimitry Andric     return;
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   auto Printf = HSAMetadataDoc->getArrayNode();
206bdd1243dSDimitry Andric   for (auto *Op : Node->operands())
2070b57cec5SDimitry Andric     if (Op->getNumOperands())
2080b57cec5SDimitry Andric       Printf.push_back(Printf.getDocument()->getNode(
2090b57cec5SDimitry Andric           cast<MDString>(Op->getOperand(0))->getString(), /*Copy=*/true));
2100b57cec5SDimitry Andric   getRootMetadata("amdhsa.printf") = Printf;
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric 
2135f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernelLanguage(const Function &Func,
2140b57cec5SDimitry Andric                                                    msgpack::MapDocNode Kern) {
2150b57cec5SDimitry Andric   // TODO: What about other languages?
2160b57cec5SDimitry Andric   auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
2170b57cec5SDimitry Andric   if (!Node || !Node->getNumOperands())
2180b57cec5SDimitry Andric     return;
2190b57cec5SDimitry Andric   auto Op0 = Node->getOperand(0);
2200b57cec5SDimitry Andric   if (Op0->getNumOperands() <= 1)
2210b57cec5SDimitry Andric     return;
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   Kern[".language"] = Kern.getDocument()->getNode("OpenCL C");
2240b57cec5SDimitry Andric   auto LanguageVersion = Kern.getDocument()->getArrayNode();
2250b57cec5SDimitry Andric   LanguageVersion.push_back(Kern.getDocument()->getNode(
2260b57cec5SDimitry Andric       mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue()));
2270b57cec5SDimitry Andric   LanguageVersion.push_back(Kern.getDocument()->getNode(
2280b57cec5SDimitry Andric       mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue()));
2290b57cec5SDimitry Andric   Kern[".language_version"] = LanguageVersion;
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric 
2325f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernelAttrs(const Function &Func,
2330b57cec5SDimitry Andric                                                 msgpack::MapDocNode Kern) {
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   if (auto Node = Func.getMetadata("reqd_work_group_size"))
2360b57cec5SDimitry Andric     Kern[".reqd_workgroup_size"] = getWorkGroupDimensions(Node);
2370b57cec5SDimitry Andric   if (auto Node = Func.getMetadata("work_group_size_hint"))
2380b57cec5SDimitry Andric     Kern[".workgroup_size_hint"] = getWorkGroupDimensions(Node);
2390b57cec5SDimitry Andric   if (auto Node = Func.getMetadata("vec_type_hint")) {
2400b57cec5SDimitry Andric     Kern[".vec_type_hint"] = Kern.getDocument()->getNode(
2410b57cec5SDimitry Andric         getTypeName(
2420b57cec5SDimitry Andric             cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
2430b57cec5SDimitry Andric             mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue()),
2440b57cec5SDimitry Andric         /*Copy=*/true);
2450b57cec5SDimitry Andric   }
2460b57cec5SDimitry Andric   if (Func.hasFnAttribute("runtime-handle")) {
2470b57cec5SDimitry Andric     Kern[".device_enqueue_symbol"] = Kern.getDocument()->getNode(
2480b57cec5SDimitry Andric         Func.getFnAttribute("runtime-handle").getValueAsString().str(),
2490b57cec5SDimitry Andric         /*Copy=*/true);
2500b57cec5SDimitry Andric   }
251349cc55cSDimitry Andric   if (Func.hasFnAttribute("device-init"))
252349cc55cSDimitry Andric     Kern[".kind"] = Kern.getDocument()->getNode("init");
253349cc55cSDimitry Andric   else if (Func.hasFnAttribute("device-fini"))
254349cc55cSDimitry Andric     Kern[".kind"] = Kern.getDocument()->getNode("fini");
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric 
2575f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernelArgs(const MachineFunction &MF,
2580b57cec5SDimitry Andric                                                msgpack::MapDocNode Kern) {
2591fd87a68SDimitry Andric   auto &Func = MF.getFunction();
2600b57cec5SDimitry Andric   unsigned Offset = 0;
2610b57cec5SDimitry Andric   auto Args = HSAMetadataDoc->getArrayNode();
2620b57cec5SDimitry Andric   for (auto &Arg : Func.args())
2630b57cec5SDimitry Andric     emitKernelArg(Arg, Offset, Args);
2640b57cec5SDimitry Andric 
2651fd87a68SDimitry Andric   emitHiddenKernelArgs(MF, Offset, Args);
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   Kern[".args"] = Args;
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric 
2705f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernelArg(const Argument &Arg,
271bdd1243dSDimitry Andric                                               unsigned &Offset,
2720b57cec5SDimitry Andric                                               msgpack::ArrayDocNode Args) {
2730b57cec5SDimitry Andric   auto Func = Arg.getParent();
2740b57cec5SDimitry Andric   auto ArgNo = Arg.getArgNo();
2750b57cec5SDimitry Andric   const MDNode *Node;
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric   StringRef Name;
2780b57cec5SDimitry Andric   Node = Func->getMetadata("kernel_arg_name");
2790b57cec5SDimitry Andric   if (Node && ArgNo < Node->getNumOperands())
2800b57cec5SDimitry Andric     Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
2810b57cec5SDimitry Andric   else if (Arg.hasName())
2820b57cec5SDimitry Andric     Name = Arg.getName();
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   StringRef TypeName;
2850b57cec5SDimitry Andric   Node = Func->getMetadata("kernel_arg_type");
2860b57cec5SDimitry Andric   if (Node && ArgNo < Node->getNumOperands())
2870b57cec5SDimitry Andric     TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric   StringRef BaseTypeName;
2900b57cec5SDimitry Andric   Node = Func->getMetadata("kernel_arg_base_type");
2910b57cec5SDimitry Andric   if (Node && ArgNo < Node->getNumOperands())
2920b57cec5SDimitry Andric     BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
2930b57cec5SDimitry Andric 
2945f757f3fSDimitry Andric   StringRef ActAccQual;
2955f757f3fSDimitry Andric   // Do we really need NoAlias check here?
2965f757f3fSDimitry Andric   if (Arg.getType()->isPointerTy() && Arg.hasNoAliasAttr()) {
2975f757f3fSDimitry Andric     if (Arg.onlyReadsMemory())
2985f757f3fSDimitry Andric       ActAccQual = "read_only";
2995f757f3fSDimitry Andric     else if (Arg.hasAttribute(Attribute::WriteOnly))
3005f757f3fSDimitry Andric       ActAccQual = "write_only";
3015f757f3fSDimitry Andric   }
3025f757f3fSDimitry Andric 
3030b57cec5SDimitry Andric   StringRef AccQual;
3040b57cec5SDimitry Andric   Node = Func->getMetadata("kernel_arg_access_qual");
3050b57cec5SDimitry Andric   if (Node && ArgNo < Node->getNumOperands())
3060b57cec5SDimitry Andric     AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric   StringRef TypeQual;
3090b57cec5SDimitry Andric   Node = Func->getMetadata("kernel_arg_type_qual");
3100b57cec5SDimitry Andric   if (Node && ArgNo < Node->getNumOperands())
3110b57cec5SDimitry Andric     TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric   const DataLayout &DL = Func->getParent()->getDataLayout();
3140b57cec5SDimitry Andric 
3155ffd83dbSDimitry Andric   MaybeAlign PointeeAlign;
316e8d8bef9SDimitry Andric   Type *Ty = Arg.hasByRefAttr() ? Arg.getParamByRefType() : Arg.getType();
317e8d8bef9SDimitry Andric 
318e8d8bef9SDimitry Andric   // FIXME: Need to distinguish in memory alignment from pointer alignment.
3190b57cec5SDimitry Andric   if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
32004eeddc0SDimitry Andric     if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS)
32104eeddc0SDimitry Andric       PointeeAlign = Arg.getParamAlign().valueOrOne();
3220b57cec5SDimitry Andric   }
3230b57cec5SDimitry Andric 
324e8d8bef9SDimitry Andric   // There's no distinction between byval aggregates and raw aggregates.
325e8d8bef9SDimitry Andric   Type *ArgTy;
326e8d8bef9SDimitry Andric   Align ArgAlign;
327e8d8bef9SDimitry Andric   std::tie(ArgTy, ArgAlign) = getArgumentTypeAlign(Arg, DL);
328e8d8bef9SDimitry Andric 
329e8d8bef9SDimitry Andric   emitKernelArg(DL, ArgTy, ArgAlign,
330e8d8bef9SDimitry Andric                 getValueKind(ArgTy, TypeQual, BaseTypeName), Offset, Args,
3315f757f3fSDimitry Andric                 PointeeAlign, Name, TypeName, BaseTypeName, ActAccQual,
3325f757f3fSDimitry Andric                 AccQual, TypeQual);
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric 
3355f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernelArg(
336e8d8bef9SDimitry Andric     const DataLayout &DL, Type *Ty, Align Alignment, StringRef ValueKind,
337e8d8bef9SDimitry Andric     unsigned &Offset, msgpack::ArrayDocNode Args, MaybeAlign PointeeAlign,
338e8d8bef9SDimitry Andric     StringRef Name, StringRef TypeName, StringRef BaseTypeName,
3395f757f3fSDimitry Andric     StringRef ActAccQual, StringRef AccQual, StringRef TypeQual) {
3400b57cec5SDimitry Andric   auto Arg = Args.getDocument()->getMapNode();
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric   if (!Name.empty())
3430b57cec5SDimitry Andric     Arg[".name"] = Arg.getDocument()->getNode(Name, /*Copy=*/true);
3440b57cec5SDimitry Andric   if (!TypeName.empty())
3450b57cec5SDimitry Andric     Arg[".type_name"] = Arg.getDocument()->getNode(TypeName, /*Copy=*/true);
3460b57cec5SDimitry Andric   auto Size = DL.getTypeAllocSize(Ty);
3470b57cec5SDimitry Andric   Arg[".size"] = Arg.getDocument()->getNode(Size);
3485ffd83dbSDimitry Andric   Offset = alignTo(Offset, Alignment);
3490b57cec5SDimitry Andric   Arg[".offset"] = Arg.getDocument()->getNode(Offset);
3500b57cec5SDimitry Andric   Offset += Size;
3510b57cec5SDimitry Andric   Arg[".value_kind"] = Arg.getDocument()->getNode(ValueKind, /*Copy=*/true);
3520b57cec5SDimitry Andric   if (PointeeAlign)
3535ffd83dbSDimitry Andric     Arg[".pointee_align"] = Arg.getDocument()->getNode(PointeeAlign->value());
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric   if (auto PtrTy = dyn_cast<PointerType>(Ty))
3560b57cec5SDimitry Andric     if (auto Qualifier = getAddressSpaceQualifier(PtrTy->getAddressSpace()))
357bdd1243dSDimitry Andric       // Limiting address space to emit only for a certain ValueKind.
358bdd1243dSDimitry Andric       if (ValueKind == "global_buffer" || ValueKind == "dynamic_shared_pointer")
359bdd1243dSDimitry Andric         Arg[".address_space"] = Arg.getDocument()->getNode(*Qualifier,
360bdd1243dSDimitry Andric                                                            /*Copy=*/true);
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric   if (auto AQ = getAccessQualifier(AccQual))
3630b57cec5SDimitry Andric     Arg[".access"] = Arg.getDocument()->getNode(*AQ, /*Copy=*/true);
3640b57cec5SDimitry Andric 
3655f757f3fSDimitry Andric   if (auto AAQ = getAccessQualifier(ActAccQual))
3665f757f3fSDimitry Andric     Arg[".actual_access"] = Arg.getDocument()->getNode(*AAQ, /*Copy=*/true);
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric   SmallVector<StringRef, 1> SplitTypeQuals;
3690b57cec5SDimitry Andric   TypeQual.split(SplitTypeQuals, " ", -1, false);
3700b57cec5SDimitry Andric   for (StringRef Key : SplitTypeQuals) {
3710b57cec5SDimitry Andric     if (Key == "const")
3720b57cec5SDimitry Andric       Arg[".is_const"] = Arg.getDocument()->getNode(true);
3730b57cec5SDimitry Andric     else if (Key == "restrict")
3740b57cec5SDimitry Andric       Arg[".is_restrict"] = Arg.getDocument()->getNode(true);
3750b57cec5SDimitry Andric     else if (Key == "volatile")
3760b57cec5SDimitry Andric       Arg[".is_volatile"] = Arg.getDocument()->getNode(true);
3770b57cec5SDimitry Andric     else if (Key == "pipe")
3780b57cec5SDimitry Andric       Arg[".is_pipe"] = Arg.getDocument()->getNode(true);
3790b57cec5SDimitry Andric   }
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric   Args.push_back(Arg);
3820b57cec5SDimitry Andric }
3830b57cec5SDimitry Andric 
3845f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitHiddenKernelArgs(
385bdd1243dSDimitry Andric     const MachineFunction &MF, unsigned &Offset, msgpack::ArrayDocNode Args) {
3861fd87a68SDimitry Andric   auto &Func = MF.getFunction();
3871fd87a68SDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
3881fd87a68SDimitry Andric 
3890eae32dcSDimitry Andric   unsigned HiddenArgNumBytes = ST.getImplicitArgNumBytes(Func);
3900b57cec5SDimitry Andric   if (!HiddenArgNumBytes)
3910b57cec5SDimitry Andric     return;
3920b57cec5SDimitry Andric 
393349cc55cSDimitry Andric   const Module *M = Func.getParent();
394349cc55cSDimitry Andric   auto &DL = M->getDataLayout();
3950b57cec5SDimitry Andric   auto Int64Ty = Type::getInt64Ty(Func.getContext());
3960b57cec5SDimitry Andric 
39781ad6265SDimitry Andric   Offset = alignTo(Offset, ST.getAlignmentForImplicitArgPtr());
39881ad6265SDimitry Andric 
3990b57cec5SDimitry Andric   if (HiddenArgNumBytes >= 8)
400e8d8bef9SDimitry Andric     emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset,
401e8d8bef9SDimitry Andric                   Args);
4020b57cec5SDimitry Andric   if (HiddenArgNumBytes >= 16)
403e8d8bef9SDimitry Andric     emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset,
404e8d8bef9SDimitry Andric                   Args);
4050b57cec5SDimitry Andric   if (HiddenArgNumBytes >= 24)
406e8d8bef9SDimitry Andric     emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset,
407e8d8bef9SDimitry Andric                   Args);
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric   auto Int8PtrTy =
4105f757f3fSDimitry Andric       PointerType::get(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric   if (HiddenArgNumBytes >= 32) {
41381ad6265SDimitry Andric     // We forbid the use of features requiring hostcall when compiling OpenCL
41481ad6265SDimitry Andric     // before code object V5, which makes the mutual exclusion between the
41581ad6265SDimitry Andric     // "printf buffer" and "hostcall buffer" here sound.
416349cc55cSDimitry Andric     if (M->getNamedMetadata("llvm.printf.fmts"))
417e8d8bef9SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset,
418e8d8bef9SDimitry Andric                     Args);
41981ad6265SDimitry Andric     else if (!Func.hasFnAttribute("amdgpu-no-hostcall-ptr"))
420e8d8bef9SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset,
421e8d8bef9SDimitry Andric                     Args);
42281ad6265SDimitry Andric     else
423e8d8bef9SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
4240b57cec5SDimitry Andric   }
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric   // Emit "default queue" and "completion action" arguments if enqueue kernel is
4270b57cec5SDimitry Andric   // used, otherwise emit dummy "none" arguments.
428bdd1243dSDimitry Andric   if (HiddenArgNumBytes >= 40) {
429bdd1243dSDimitry Andric     if (!Func.hasFnAttribute("amdgpu-no-default-queue")) {
430e8d8bef9SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset,
431e8d8bef9SDimitry Andric                     Args);
4320b57cec5SDimitry Andric     } else {
433e8d8bef9SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
434bdd1243dSDimitry Andric     }
435bdd1243dSDimitry Andric   }
436bdd1243dSDimitry Andric 
437bdd1243dSDimitry Andric   if (HiddenArgNumBytes >= 48) {
43806c3fb27SDimitry Andric     if (!Func.hasFnAttribute("amdgpu-no-completion-action")) {
439bdd1243dSDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset,
440bdd1243dSDimitry Andric                     Args);
441bdd1243dSDimitry Andric     } else {
442e8d8bef9SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
4430b57cec5SDimitry Andric     }
4440b57cec5SDimitry Andric   }
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   // Emit the pointer argument for multi-grid object.
44781ad6265SDimitry Andric   if (HiddenArgNumBytes >= 56) {
44881ad6265SDimitry Andric     if (!Func.hasFnAttribute("amdgpu-no-multigrid-sync-arg")) {
449e8d8bef9SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset,
450e8d8bef9SDimitry Andric                     Args);
45181ad6265SDimitry Andric     } else {
45281ad6265SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
45381ad6265SDimitry Andric     }
45481ad6265SDimitry Andric   }
4550b57cec5SDimitry Andric }
4560b57cec5SDimitry Andric 
4575f757f3fSDimitry Andric msgpack::MapDocNode
4585f757f3fSDimitry Andric MetadataStreamerMsgPackV4::getHSAKernelProps(const MachineFunction &MF,
4595f757f3fSDimitry Andric                                              const SIProgramInfo &ProgramInfo,
46006c3fb27SDimitry Andric                                              unsigned CodeObjectVersion) const {
4610b57cec5SDimitry Andric   const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
4620b57cec5SDimitry Andric   const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
4630b57cec5SDimitry Andric   const Function &F = MF.getFunction();
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric   auto Kern = HSAMetadataDoc->getMapNode();
4660b57cec5SDimitry Andric 
4678bcb0991SDimitry Andric   Align MaxKernArgAlign;
4680b57cec5SDimitry Andric   Kern[".kernarg_segment_size"] = Kern.getDocument()->getNode(
4690b57cec5SDimitry Andric       STM.getKernArgSegmentSize(F, MaxKernArgAlign));
4700b57cec5SDimitry Andric   Kern[".group_segment_fixed_size"] =
4710b57cec5SDimitry Andric       Kern.getDocument()->getNode(ProgramInfo.LDSSize);
4720b57cec5SDimitry Andric   Kern[".private_segment_fixed_size"] =
4730b57cec5SDimitry Andric       Kern.getDocument()->getNode(ProgramInfo.ScratchSize);
47406c3fb27SDimitry Andric   if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5)
475fcaf7f86SDimitry Andric     Kern[".uses_dynamic_stack"] =
476fcaf7f86SDimitry Andric         Kern.getDocument()->getNode(ProgramInfo.DynamicCallStack);
47706c3fb27SDimitry Andric 
47806c3fb27SDimitry Andric   if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5 && STM.supportsWGP())
479bdd1243dSDimitry Andric     Kern[".workgroup_processor_mode"] =
480bdd1243dSDimitry Andric         Kern.getDocument()->getNode(ProgramInfo.WgpMode);
481349cc55cSDimitry Andric 
482349cc55cSDimitry Andric   // FIXME: The metadata treats the minimum as 16?
4830b57cec5SDimitry Andric   Kern[".kernarg_segment_align"] =
4848bcb0991SDimitry Andric       Kern.getDocument()->getNode(std::max(Align(4), MaxKernArgAlign).value());
4850b57cec5SDimitry Andric   Kern[".wavefront_size"] =
4860b57cec5SDimitry Andric       Kern.getDocument()->getNode(STM.getWavefrontSize());
4870b57cec5SDimitry Andric   Kern[".sgpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumSGPR);
4880b57cec5SDimitry Andric   Kern[".vgpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumVGPR);
48981ad6265SDimitry Andric 
49081ad6265SDimitry Andric   // Only add AGPR count to metadata for supported devices
49181ad6265SDimitry Andric   if (STM.hasMAIInsts()) {
49281ad6265SDimitry Andric     Kern[".agpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumAccVGPR);
49381ad6265SDimitry Andric   }
49481ad6265SDimitry Andric 
4950b57cec5SDimitry Andric   Kern[".max_flat_workgroup_size"] =
4960b57cec5SDimitry Andric       Kern.getDocument()->getNode(MFI.getMaxFlatWorkGroupSize());
4970b57cec5SDimitry Andric   Kern[".sgpr_spill_count"] =
4980b57cec5SDimitry Andric       Kern.getDocument()->getNode(MFI.getNumSpilledSGPRs());
4990b57cec5SDimitry Andric   Kern[".vgpr_spill_count"] =
5000b57cec5SDimitry Andric       Kern.getDocument()->getNode(MFI.getNumSpilledVGPRs());
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   return Kern;
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric 
5055f757f3fSDimitry Andric bool MetadataStreamerMsgPackV4::emitTo(AMDGPUTargetStreamer &TargetStreamer) {
5060b57cec5SDimitry Andric   return TargetStreamer.EmitHSAMetadata(*HSAMetadataDoc, true);
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric 
5095f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::begin(const Module &Mod,
510fe6060f1SDimitry Andric                                       const IsaInfo::AMDGPUTargetID &TargetID) {
5110b57cec5SDimitry Andric   emitVersion();
5125f757f3fSDimitry Andric   emitTargetID(TargetID);
5130b57cec5SDimitry Andric   emitPrintf(Mod);
5140b57cec5SDimitry Andric   getRootMetadata("amdhsa.kernels") = HSAMetadataDoc->getArrayNode();
5150b57cec5SDimitry Andric }
5160b57cec5SDimitry Andric 
5175f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::end() {
5180b57cec5SDimitry Andric   std::string HSAMetadataString;
5190b57cec5SDimitry Andric   raw_string_ostream StrOS(HSAMetadataString);
5200b57cec5SDimitry Andric   HSAMetadataDoc->toYAML(StrOS);
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric   if (DumpHSAMetadata)
5230b57cec5SDimitry Andric     dump(StrOS.str());
5240b57cec5SDimitry Andric   if (VerifyHSAMetadata)
5250b57cec5SDimitry Andric     verify(StrOS.str());
5260b57cec5SDimitry Andric }
5270b57cec5SDimitry Andric 
5285f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernel(const MachineFunction &MF,
5290b57cec5SDimitry Andric                                            const SIProgramInfo &ProgramInfo) {
5300b57cec5SDimitry Andric   auto &Func = MF.getFunction();
53106c3fb27SDimitry Andric   if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL &&
53206c3fb27SDimitry Andric       Func.getCallingConv() != CallingConv::SPIR_KERNEL)
53306c3fb27SDimitry Andric     return;
5340b57cec5SDimitry Andric 
53506c3fb27SDimitry Andric   auto CodeObjectVersion = AMDGPU::getCodeObjectVersion(*Func.getParent());
53606c3fb27SDimitry Andric   auto Kern = getHSAKernelProps(MF, ProgramInfo, CodeObjectVersion);
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric   auto Kernels =
5390b57cec5SDimitry Andric       getRootMetadata("amdhsa.kernels").getArray(/*Convert=*/true);
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric   {
5420b57cec5SDimitry Andric     Kern[".name"] = Kern.getDocument()->getNode(Func.getName());
5430b57cec5SDimitry Andric     Kern[".symbol"] = Kern.getDocument()->getNode(
5440b57cec5SDimitry Andric         (Twine(Func.getName()) + Twine(".kd")).str(), /*Copy=*/true);
5450b57cec5SDimitry Andric     emitKernelLanguage(Func, Kern);
5460b57cec5SDimitry Andric     emitKernelAttrs(Func, Kern);
5471fd87a68SDimitry Andric     emitKernelArgs(MF, Kern);
5480b57cec5SDimitry Andric   }
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric   Kernels.push_back(Kern);
5510b57cec5SDimitry Andric }
5520b57cec5SDimitry Andric 
553fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
5541fd87a68SDimitry Andric // HSAMetadataStreamerV5
5551fd87a68SDimitry Andric //===----------------------------------------------------------------------===//
5561fd87a68SDimitry Andric 
557bdd1243dSDimitry Andric void MetadataStreamerMsgPackV5::emitVersion() {
5581fd87a68SDimitry Andric   auto Version = HSAMetadataDoc->getArrayNode();
5591fd87a68SDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMajorV5));
5601fd87a68SDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMinorV5));
5611fd87a68SDimitry Andric   getRootMetadata("amdhsa.version") = Version;
5621fd87a68SDimitry Andric }
5631fd87a68SDimitry Andric 
564bdd1243dSDimitry Andric void MetadataStreamerMsgPackV5::emitHiddenKernelArgs(
565bdd1243dSDimitry Andric     const MachineFunction &MF, unsigned &Offset, msgpack::ArrayDocNode Args) {
5661fd87a68SDimitry Andric   auto &Func = MF.getFunction();
5671fd87a68SDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
56881ad6265SDimitry Andric 
56981ad6265SDimitry Andric   // No implicit kernel argument is used.
57081ad6265SDimitry Andric   if (ST.getImplicitArgNumBytes(Func) == 0)
57181ad6265SDimitry Andric     return;
57281ad6265SDimitry Andric 
5731fd87a68SDimitry Andric   const Module *M = Func.getParent();
5741fd87a68SDimitry Andric   auto &DL = M->getDataLayout();
57581ad6265SDimitry Andric   const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
5761fd87a68SDimitry Andric 
5771fd87a68SDimitry Andric   auto Int64Ty = Type::getInt64Ty(Func.getContext());
5781fd87a68SDimitry Andric   auto Int32Ty = Type::getInt32Ty(Func.getContext());
5791fd87a68SDimitry Andric   auto Int16Ty = Type::getInt16Ty(Func.getContext());
5801fd87a68SDimitry Andric 
58181ad6265SDimitry Andric   Offset = alignTo(Offset, ST.getAlignmentForImplicitArgPtr());
5821fd87a68SDimitry Andric   emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_x", Offset, Args);
5831fd87a68SDimitry Andric   emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_y", Offset, Args);
5841fd87a68SDimitry Andric   emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_z", Offset, Args);
5851fd87a68SDimitry Andric 
5861fd87a68SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_x", Offset, Args);
5871fd87a68SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_y", Offset, Args);
5881fd87a68SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_z", Offset, Args);
5891fd87a68SDimitry Andric 
5901fd87a68SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_x", Offset, Args);
5911fd87a68SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_y", Offset, Args);
5921fd87a68SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_z", Offset, Args);
5931fd87a68SDimitry Andric 
5941fd87a68SDimitry Andric   // Reserved for hidden_tool_correlation_id.
5951fd87a68SDimitry Andric   Offset += 8;
5961fd87a68SDimitry Andric 
5971fd87a68SDimitry Andric   Offset += 8; // Reserved.
5981fd87a68SDimitry Andric 
5991fd87a68SDimitry Andric   emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset, Args);
6001fd87a68SDimitry Andric   emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset, Args);
6011fd87a68SDimitry Andric   emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset, Args);
6021fd87a68SDimitry Andric 
6031fd87a68SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_grid_dims", Offset, Args);
6041fd87a68SDimitry Andric 
6051fd87a68SDimitry Andric   Offset += 6; // Reserved.
6061fd87a68SDimitry Andric   auto Int8PtrTy =
6075f757f3fSDimitry Andric       PointerType::get(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
6081fd87a68SDimitry Andric 
6091fd87a68SDimitry Andric   if (M->getNamedMetadata("llvm.printf.fmts")) {
6101fd87a68SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset,
6111fd87a68SDimitry Andric                   Args);
61281ad6265SDimitry Andric   } else {
6131fd87a68SDimitry Andric     Offset += 8; // Skipped.
61481ad6265SDimitry Andric   }
6151fd87a68SDimitry Andric 
61681ad6265SDimitry Andric   if (!Func.hasFnAttribute("amdgpu-no-hostcall-ptr")) {
6171fd87a68SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset,
6181fd87a68SDimitry Andric                   Args);
61981ad6265SDimitry Andric   } else {
6201fd87a68SDimitry Andric     Offset += 8; // Skipped.
62181ad6265SDimitry Andric   }
6221fd87a68SDimitry Andric 
62381ad6265SDimitry Andric   if (!Func.hasFnAttribute("amdgpu-no-multigrid-sync-arg")) {
6241fd87a68SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset,
6251fd87a68SDimitry Andric                 Args);
62681ad6265SDimitry Andric   } else {
62781ad6265SDimitry Andric     Offset += 8; // Skipped.
62881ad6265SDimitry Andric   }
6291fd87a68SDimitry Andric 
63081ad6265SDimitry Andric   if (!Func.hasFnAttribute("amdgpu-no-heap-ptr"))
63181ad6265SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_heap_v1", Offset, Args);
63281ad6265SDimitry Andric   else
63381ad6265SDimitry Andric     Offset += 8; // Skipped.
6341fd87a68SDimitry Andric 
635bdd1243dSDimitry Andric   if (!Func.hasFnAttribute("amdgpu-no-default-queue")) {
6361fd87a68SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset,
6371fd87a68SDimitry Andric                   Args);
638bdd1243dSDimitry Andric   } else {
639bdd1243dSDimitry Andric     Offset += 8; // Skipped.
640bdd1243dSDimitry Andric   }
641bdd1243dSDimitry Andric 
64206c3fb27SDimitry Andric   if (!Func.hasFnAttribute("amdgpu-no-completion-action")) {
6431fd87a68SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset,
6441fd87a68SDimitry Andric                   Args);
64581ad6265SDimitry Andric   } else {
646bdd1243dSDimitry Andric     Offset += 8; // Skipped.
64781ad6265SDimitry Andric   }
6481fd87a68SDimitry Andric 
649*1db9f3b2SDimitry Andric   // Emit argument for hidden dynamic lds size
650*1db9f3b2SDimitry Andric   if (MFI.isDynamicLDSUsed()) {
651*1db9f3b2SDimitry Andric     emitKernelArg(DL, Int32Ty, Align(4), "hidden_dynamic_lds_size", Offset,
652*1db9f3b2SDimitry Andric                   Args);
653*1db9f3b2SDimitry Andric   } else {
654*1db9f3b2SDimitry Andric     Offset += 4; // skipped
655*1db9f3b2SDimitry Andric   }
656*1db9f3b2SDimitry Andric 
657*1db9f3b2SDimitry Andric   Offset += 68; // Reserved.
6581fd87a68SDimitry Andric 
65981ad6265SDimitry Andric   // hidden_private_base and hidden_shared_base are only when the subtarget has
66081ad6265SDimitry Andric   // ApertureRegs.
66181ad6265SDimitry Andric   if (!ST.hasApertureRegs()) {
6621fd87a68SDimitry Andric     emitKernelArg(DL, Int32Ty, Align(4), "hidden_private_base", Offset, Args);
6631fd87a68SDimitry Andric     emitKernelArg(DL, Int32Ty, Align(4), "hidden_shared_base", Offset, Args);
66481ad6265SDimitry Andric   } else {
6651fd87a68SDimitry Andric     Offset += 8; // Skipped.
66681ad6265SDimitry Andric   }
6671fd87a68SDimitry Andric 
6685f757f3fSDimitry Andric   if (MFI.getUserSGPRInfo().hasQueuePtr())
6691fd87a68SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_queue_ptr", Offset, Args);
6701fd87a68SDimitry Andric }
6711fd87a68SDimitry Andric 
672bdd1243dSDimitry Andric void MetadataStreamerMsgPackV5::emitKernelAttrs(const Function &Func,
673bdd1243dSDimitry Andric                                                 msgpack::MapDocNode Kern) {
6745f757f3fSDimitry Andric   MetadataStreamerMsgPackV4::emitKernelAttrs(Func, Kern);
675bdd1243dSDimitry Andric 
676bdd1243dSDimitry Andric   if (Func.getFnAttribute("uniform-work-group-size").getValueAsBool())
677bdd1243dSDimitry Andric     Kern[".uniform_work_group_size"] = Kern.getDocument()->getNode(1);
678bdd1243dSDimitry Andric }
679bdd1243dSDimitry Andric 
680bdd1243dSDimitry Andric 
6810b57cec5SDimitry Andric } // end namespace HSAMD
6820b57cec5SDimitry Andric } // end namespace AMDGPU
6830b57cec5SDimitry Andric } // end namespace llvm
684