xref: /src/contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1044eb2f6SDimitry Andric //===--- AMDGPUHSAMetadataStreamer.cpp --------------------------*- C++ -*-===//
271d5a254SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
671d5a254SDimitry Andric //
771d5a254SDimitry Andric //===----------------------------------------------------------------------===//
871d5a254SDimitry Andric //
971d5a254SDimitry Andric /// \file
10eb11fae6SDimitry Andric /// AMDGPU HSA Metadata Streamer.
1171d5a254SDimitry Andric ///
1271d5a254SDimitry Andric //
1371d5a254SDimitry Andric //===----------------------------------------------------------------------===//
1471d5a254SDimitry Andric 
15044eb2f6SDimitry Andric #include "AMDGPUHSAMetadataStreamer.h"
167ab83427SDimitry Andric #include "AMDGPU.h"
17b60736ecSDimitry Andric #include "GCNSubtarget.h"
18d8e91e46SDimitry Andric #include "MCTargetDesc/AMDGPUTargetStreamer.h"
19eb11fae6SDimitry Andric #include "SIMachineFunctionInfo.h"
20eb11fae6SDimitry Andric #include "SIProgramInfo.h"
2171d5a254SDimitry Andric #include "llvm/IR/Module.h"
22ac9a064cSDimitry Andric #include "llvm/MC/MCContext.h"
23ac9a064cSDimitry Andric #include "llvm/MC/MCExpr.h"
24b60736ecSDimitry Andric using namespace llvm;
25b60736ecSDimitry Andric 
getArgumentTypeAlign(const Argument & Arg,const DataLayout & DL)26b60736ecSDimitry Andric static std::pair<Type *, Align> getArgumentTypeAlign(const Argument &Arg,
27b60736ecSDimitry Andric                                                      const DataLayout &DL) {
28b60736ecSDimitry Andric   Type *Ty = Arg.getType();
29b60736ecSDimitry Andric   MaybeAlign ArgAlign;
30b60736ecSDimitry Andric   if (Arg.hasByRefAttr()) {
31b60736ecSDimitry Andric     Ty = Arg.getParamByRefType();
32b60736ecSDimitry Andric     ArgAlign = Arg.getParamAlign();
33b60736ecSDimitry Andric   }
34b60736ecSDimitry Andric 
35b60736ecSDimitry Andric   if (!ArgAlign)
36b60736ecSDimitry Andric     ArgAlign = DL.getABITypeAlign(Ty);
37b60736ecSDimitry Andric 
38e3b55780SDimitry Andric   return std::pair(Ty, *ArgAlign);
39b60736ecSDimitry Andric }
4071d5a254SDimitry Andric 
4171d5a254SDimitry Andric namespace llvm {
4271d5a254SDimitry Andric 
43044eb2f6SDimitry Andric static cl::opt<bool> DumpHSAMetadata(
44044eb2f6SDimitry Andric     "amdgpu-dump-hsa-metadata",
45044eb2f6SDimitry Andric     cl::desc("Dump AMDGPU HSA Metadata"));
46044eb2f6SDimitry Andric static cl::opt<bool> VerifyHSAMetadata(
47044eb2f6SDimitry Andric     "amdgpu-verify-hsa-metadata",
48044eb2f6SDimitry Andric     cl::desc("Verify AMDGPU HSA Metadata"));
4971d5a254SDimitry Andric 
50ac9a064cSDimitry Andric namespace AMDGPU::HSAMD {
5171d5a254SDimitry Andric 
52d8e91e46SDimitry Andric //===----------------------------------------------------------------------===//
53b1c73532SDimitry Andric // HSAMetadataStreamerV4
54d8e91e46SDimitry Andric //===----------------------------------------------------------------------===//
55b1c73532SDimitry Andric 
dump(StringRef HSAMetadataString) const56b1c73532SDimitry Andric void MetadataStreamerMsgPackV4::dump(StringRef HSAMetadataString) const {
57044eb2f6SDimitry Andric   errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
5871d5a254SDimitry Andric }
5971d5a254SDimitry Andric 
verify(StringRef HSAMetadataString) const60b1c73532SDimitry Andric void MetadataStreamerMsgPackV4::verify(StringRef HSAMetadataString) const {
61d8e91e46SDimitry Andric   errs() << "AMDGPU HSA Metadata Parser Test: ";
62d8e91e46SDimitry Andric 
63e6d15924SDimitry Andric   msgpack::Document FromHSAMetadataString;
64d8e91e46SDimitry Andric 
65e6d15924SDimitry Andric   if (!FromHSAMetadataString.fromYAML(HSAMetadataString)) {
66d8e91e46SDimitry Andric     errs() << "FAIL\n";
67d8e91e46SDimitry Andric     return;
68d8e91e46SDimitry Andric   }
69d8e91e46SDimitry Andric 
70d8e91e46SDimitry Andric   std::string ToHSAMetadataString;
71d8e91e46SDimitry Andric   raw_string_ostream StrOS(ToHSAMetadataString);
72e6d15924SDimitry Andric   FromHSAMetadataString.toYAML(StrOS);
73d8e91e46SDimitry Andric 
74d8e91e46SDimitry Andric   errs() << (HSAMetadataString == StrOS.str() ? "PASS" : "FAIL") << '\n';
75d8e91e46SDimitry Andric   if (HSAMetadataString != ToHSAMetadataString) {
76d8e91e46SDimitry Andric     errs() << "Original input: " << HSAMetadataString << '\n'
77d8e91e46SDimitry Andric            << "Produced output: " << StrOS.str() << '\n';
78d8e91e46SDimitry Andric   }
79d8e91e46SDimitry Andric }
80d8e91e46SDimitry Andric 
81e3b55780SDimitry Andric std::optional<StringRef>
getAccessQualifier(StringRef AccQual) const82b1c73532SDimitry Andric MetadataStreamerMsgPackV4::getAccessQualifier(StringRef AccQual) const {
83e3b55780SDimitry Andric   return StringSwitch<std::optional<StringRef>>(AccQual)
84d8e91e46SDimitry Andric       .Case("read_only", StringRef("read_only"))
85d8e91e46SDimitry Andric       .Case("write_only", StringRef("write_only"))
86d8e91e46SDimitry Andric       .Case("read_write", StringRef("read_write"))
87e3b55780SDimitry Andric       .Default(std::nullopt);
88d8e91e46SDimitry Andric }
89d8e91e46SDimitry Andric 
getAddressSpaceQualifier(unsigned AddressSpace) const90b1c73532SDimitry Andric std::optional<StringRef> MetadataStreamerMsgPackV4::getAddressSpaceQualifier(
91e3b55780SDimitry Andric     unsigned AddressSpace) const {
92d8e91e46SDimitry Andric   switch (AddressSpace) {
93d8e91e46SDimitry Andric   case AMDGPUAS::PRIVATE_ADDRESS:
94d8e91e46SDimitry Andric     return StringRef("private");
95d8e91e46SDimitry Andric   case AMDGPUAS::GLOBAL_ADDRESS:
96d8e91e46SDimitry Andric     return StringRef("global");
97d8e91e46SDimitry Andric   case AMDGPUAS::CONSTANT_ADDRESS:
98d8e91e46SDimitry Andric     return StringRef("constant");
99d8e91e46SDimitry Andric   case AMDGPUAS::LOCAL_ADDRESS:
100d8e91e46SDimitry Andric     return StringRef("local");
101d8e91e46SDimitry Andric   case AMDGPUAS::FLAT_ADDRESS:
102d8e91e46SDimitry Andric     return StringRef("generic");
103d8e91e46SDimitry Andric   case AMDGPUAS::REGION_ADDRESS:
104d8e91e46SDimitry Andric     return StringRef("region");
105d8e91e46SDimitry Andric   default:
106e3b55780SDimitry Andric     return std::nullopt;
107d8e91e46SDimitry Andric   }
108d8e91e46SDimitry Andric }
109d8e91e46SDimitry Andric 
110e3b55780SDimitry Andric StringRef
getValueKind(Type * Ty,StringRef TypeQual,StringRef BaseTypeName) const111b1c73532SDimitry Andric MetadataStreamerMsgPackV4::getValueKind(Type *Ty, StringRef TypeQual,
112d8e91e46SDimitry Andric                                         StringRef BaseTypeName) const {
113c0981da4SDimitry Andric   if (TypeQual.contains("pipe"))
114d8e91e46SDimitry Andric     return "pipe";
115d8e91e46SDimitry Andric 
116d8e91e46SDimitry Andric   return StringSwitch<StringRef>(BaseTypeName)
117d8e91e46SDimitry Andric       .Case("image1d_t", "image")
118d8e91e46SDimitry Andric       .Case("image1d_array_t", "image")
119d8e91e46SDimitry Andric       .Case("image1d_buffer_t", "image")
120d8e91e46SDimitry Andric       .Case("image2d_t", "image")
121d8e91e46SDimitry Andric       .Case("image2d_array_t", "image")
122d8e91e46SDimitry Andric       .Case("image2d_array_depth_t", "image")
123d8e91e46SDimitry Andric       .Case("image2d_array_msaa_t", "image")
124d8e91e46SDimitry Andric       .Case("image2d_array_msaa_depth_t", "image")
125d8e91e46SDimitry Andric       .Case("image2d_depth_t", "image")
126d8e91e46SDimitry Andric       .Case("image2d_msaa_t", "image")
127d8e91e46SDimitry Andric       .Case("image2d_msaa_depth_t", "image")
128d8e91e46SDimitry Andric       .Case("image3d_t", "image")
129d8e91e46SDimitry Andric       .Case("sampler_t", "sampler")
130d8e91e46SDimitry Andric       .Case("queue_t", "queue")
131d8e91e46SDimitry Andric       .Default(isa<PointerType>(Ty)
132d8e91e46SDimitry Andric                    ? (Ty->getPointerAddressSpace() == AMDGPUAS::LOCAL_ADDRESS
133d8e91e46SDimitry Andric                           ? "dynamic_shared_pointer"
134d8e91e46SDimitry Andric                           : "global_buffer")
135d8e91e46SDimitry Andric                    : "by_value");
136d8e91e46SDimitry Andric }
137d8e91e46SDimitry Andric 
getTypeName(Type * Ty,bool Signed) const138b1c73532SDimitry Andric std::string MetadataStreamerMsgPackV4::getTypeName(Type *Ty,
139e3b55780SDimitry Andric                                                    bool Signed) const {
140d8e91e46SDimitry Andric   switch (Ty->getTypeID()) {
141d8e91e46SDimitry Andric   case Type::IntegerTyID: {
142d8e91e46SDimitry Andric     if (!Signed)
143d8e91e46SDimitry Andric       return (Twine('u') + getTypeName(Ty, true)).str();
144d8e91e46SDimitry Andric 
145d8e91e46SDimitry Andric     auto BitWidth = Ty->getIntegerBitWidth();
146d8e91e46SDimitry Andric     switch (BitWidth) {
147d8e91e46SDimitry Andric     case 8:
148d8e91e46SDimitry Andric       return "char";
149d8e91e46SDimitry Andric     case 16:
150d8e91e46SDimitry Andric       return "short";
151d8e91e46SDimitry Andric     case 32:
152d8e91e46SDimitry Andric       return "int";
153d8e91e46SDimitry Andric     case 64:
154d8e91e46SDimitry Andric       return "long";
155d8e91e46SDimitry Andric     default:
156d8e91e46SDimitry Andric       return (Twine('i') + Twine(BitWidth)).str();
157d8e91e46SDimitry Andric     }
158d8e91e46SDimitry Andric   }
159d8e91e46SDimitry Andric   case Type::HalfTyID:
160d8e91e46SDimitry Andric     return "half";
161d8e91e46SDimitry Andric   case Type::FloatTyID:
162d8e91e46SDimitry Andric     return "float";
163d8e91e46SDimitry Andric   case Type::DoubleTyID:
164d8e91e46SDimitry Andric     return "double";
165cfca06d7SDimitry Andric   case Type::FixedVectorTyID: {
166cfca06d7SDimitry Andric     auto VecTy = cast<FixedVectorType>(Ty);
167d8e91e46SDimitry Andric     auto ElTy = VecTy->getElementType();
168cfca06d7SDimitry Andric     auto NumElements = VecTy->getNumElements();
169d8e91e46SDimitry Andric     return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
170d8e91e46SDimitry Andric   }
171d8e91e46SDimitry Andric   default:
172d8e91e46SDimitry Andric     return "unknown";
173d8e91e46SDimitry Andric   }
174d8e91e46SDimitry Andric }
175d8e91e46SDimitry Andric 
176e6d15924SDimitry Andric msgpack::ArrayDocNode
getWorkGroupDimensions(MDNode * Node) const177b1c73532SDimitry Andric MetadataStreamerMsgPackV4::getWorkGroupDimensions(MDNode *Node) const {
178e6d15924SDimitry Andric   auto Dims = HSAMetadataDoc->getArrayNode();
179d8e91e46SDimitry Andric   if (Node->getNumOperands() != 3)
180d8e91e46SDimitry Andric     return Dims;
181d8e91e46SDimitry Andric 
182d8e91e46SDimitry Andric   for (auto &Op : Node->operands())
183e6d15924SDimitry Andric     Dims.push_back(Dims.getDocument()->getNode(
184e6d15924SDimitry Andric         uint64_t(mdconst::extract<ConstantInt>(Op)->getZExtValue())));
185d8e91e46SDimitry Andric   return Dims;
186d8e91e46SDimitry Andric }
187d8e91e46SDimitry Andric 
emitVersion()188b1c73532SDimitry Andric void MetadataStreamerMsgPackV4::emitVersion() {
189e6d15924SDimitry Andric   auto Version = HSAMetadataDoc->getArrayNode();
190b1c73532SDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMajorV4));
191b1c73532SDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMinorV4));
192e6d15924SDimitry Andric   getRootMetadata("amdhsa.version") = Version;
193d8e91e46SDimitry Andric }
194d8e91e46SDimitry Andric 
emitTargetID(const IsaInfo::AMDGPUTargetID & TargetID)195b1c73532SDimitry Andric void MetadataStreamerMsgPackV4::emitTargetID(
196b1c73532SDimitry Andric     const IsaInfo::AMDGPUTargetID &TargetID) {
197b1c73532SDimitry Andric   getRootMetadata("amdhsa.target") =
198b1c73532SDimitry Andric       HSAMetadataDoc->getNode(TargetID.toString(), /*Copy=*/true);
199b1c73532SDimitry Andric }
200b1c73532SDimitry Andric 
emitPrintf(const Module & Mod)201b1c73532SDimitry Andric void MetadataStreamerMsgPackV4::emitPrintf(const Module &Mod) {
202d8e91e46SDimitry Andric   auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
203d8e91e46SDimitry Andric   if (!Node)
204d8e91e46SDimitry Andric     return;
205d8e91e46SDimitry Andric 
206e6d15924SDimitry Andric   auto Printf = HSAMetadataDoc->getArrayNode();
207e3b55780SDimitry Andric   for (auto *Op : Node->operands())
208d8e91e46SDimitry Andric     if (Op->getNumOperands())
209e6d15924SDimitry Andric       Printf.push_back(Printf.getDocument()->getNode(
210e6d15924SDimitry Andric           cast<MDString>(Op->getOperand(0))->getString(), /*Copy=*/true));
211e6d15924SDimitry Andric   getRootMetadata("amdhsa.printf") = Printf;
212d8e91e46SDimitry Andric }
213d8e91e46SDimitry Andric 
emitKernelLanguage(const Function & Func,msgpack::MapDocNode Kern)214b1c73532SDimitry Andric void MetadataStreamerMsgPackV4::emitKernelLanguage(const Function &Func,
215e6d15924SDimitry Andric                                                    msgpack::MapDocNode Kern) {
216d8e91e46SDimitry Andric   // TODO: What about other languages?
217d8e91e46SDimitry Andric   auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
218d8e91e46SDimitry Andric   if (!Node || !Node->getNumOperands())
219d8e91e46SDimitry Andric     return;
220d8e91e46SDimitry Andric   auto Op0 = Node->getOperand(0);
221d8e91e46SDimitry Andric   if (Op0->getNumOperands() <= 1)
222d8e91e46SDimitry Andric     return;
223d8e91e46SDimitry Andric 
224e6d15924SDimitry Andric   Kern[".language"] = Kern.getDocument()->getNode("OpenCL C");
225e6d15924SDimitry Andric   auto LanguageVersion = Kern.getDocument()->getArrayNode();
226e6d15924SDimitry Andric   LanguageVersion.push_back(Kern.getDocument()->getNode(
227d8e91e46SDimitry Andric       mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue()));
228e6d15924SDimitry Andric   LanguageVersion.push_back(Kern.getDocument()->getNode(
229d8e91e46SDimitry Andric       mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue()));
230e6d15924SDimitry Andric   Kern[".language_version"] = LanguageVersion;
231d8e91e46SDimitry Andric }
232d8e91e46SDimitry Andric 
emitKernelAttrs(const Function & Func,msgpack::MapDocNode Kern)233b1c73532SDimitry Andric void MetadataStreamerMsgPackV4::emitKernelAttrs(const Function &Func,
234e6d15924SDimitry Andric                                                 msgpack::MapDocNode Kern) {
235d8e91e46SDimitry Andric 
236d8e91e46SDimitry Andric   if (auto Node = Func.getMetadata("reqd_work_group_size"))
237d8e91e46SDimitry Andric     Kern[".reqd_workgroup_size"] = getWorkGroupDimensions(Node);
238d8e91e46SDimitry Andric   if (auto Node = Func.getMetadata("work_group_size_hint"))
239d8e91e46SDimitry Andric     Kern[".workgroup_size_hint"] = getWorkGroupDimensions(Node);
240d8e91e46SDimitry Andric   if (auto Node = Func.getMetadata("vec_type_hint")) {
241e6d15924SDimitry Andric     Kern[".vec_type_hint"] = Kern.getDocument()->getNode(
242e6d15924SDimitry Andric         getTypeName(
243d8e91e46SDimitry Andric             cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
244e6d15924SDimitry Andric             mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue()),
245e6d15924SDimitry Andric         /*Copy=*/true);
246d8e91e46SDimitry Andric   }
247d8e91e46SDimitry Andric   if (Func.hasFnAttribute("runtime-handle")) {
248e6d15924SDimitry Andric     Kern[".device_enqueue_symbol"] = Kern.getDocument()->getNode(
249e6d15924SDimitry Andric         Func.getFnAttribute("runtime-handle").getValueAsString().str(),
250e6d15924SDimitry Andric         /*Copy=*/true);
251d8e91e46SDimitry Andric   }
252c0981da4SDimitry Andric   if (Func.hasFnAttribute("device-init"))
253c0981da4SDimitry Andric     Kern[".kind"] = Kern.getDocument()->getNode("init");
254c0981da4SDimitry Andric   else if (Func.hasFnAttribute("device-fini"))
255c0981da4SDimitry Andric     Kern[".kind"] = Kern.getDocument()->getNode("fini");
256d8e91e46SDimitry Andric }
257d8e91e46SDimitry Andric 
emitKernelArgs(const MachineFunction & MF,msgpack::MapDocNode Kern)258b1c73532SDimitry Andric void MetadataStreamerMsgPackV4::emitKernelArgs(const MachineFunction &MF,
259e6d15924SDimitry Andric                                                msgpack::MapDocNode Kern) {
260ecbca9f5SDimitry Andric   auto &Func = MF.getFunction();
261d8e91e46SDimitry Andric   unsigned Offset = 0;
262e6d15924SDimitry Andric   auto Args = HSAMetadataDoc->getArrayNode();
263d8e91e46SDimitry Andric   for (auto &Arg : Func.args())
264e6d15924SDimitry Andric     emitKernelArg(Arg, Offset, Args);
265d8e91e46SDimitry Andric 
266ecbca9f5SDimitry Andric   emitHiddenKernelArgs(MF, Offset, Args);
267d8e91e46SDimitry Andric 
268e6d15924SDimitry Andric   Kern[".args"] = Args;
269d8e91e46SDimitry Andric }
270d8e91e46SDimitry Andric 
emitKernelArg(const Argument & Arg,unsigned & Offset,msgpack::ArrayDocNode Args)271b1c73532SDimitry Andric void MetadataStreamerMsgPackV4::emitKernelArg(const Argument &Arg,
272e3b55780SDimitry Andric                                               unsigned &Offset,
273e6d15924SDimitry Andric                                               msgpack::ArrayDocNode Args) {
274d8e91e46SDimitry Andric   auto Func = Arg.getParent();
275d8e91e46SDimitry Andric   auto ArgNo = Arg.getArgNo();
276d8e91e46SDimitry Andric   const MDNode *Node;
277d8e91e46SDimitry Andric 
278d8e91e46SDimitry Andric   StringRef Name;
279d8e91e46SDimitry Andric   Node = Func->getMetadata("kernel_arg_name");
280d8e91e46SDimitry Andric   if (Node && ArgNo < Node->getNumOperands())
281d8e91e46SDimitry Andric     Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
282d8e91e46SDimitry Andric   else if (Arg.hasName())
283d8e91e46SDimitry Andric     Name = Arg.getName();
284d8e91e46SDimitry Andric 
285d8e91e46SDimitry Andric   StringRef TypeName;
286d8e91e46SDimitry Andric   Node = Func->getMetadata("kernel_arg_type");
287d8e91e46SDimitry Andric   if (Node && ArgNo < Node->getNumOperands())
288d8e91e46SDimitry Andric     TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
289d8e91e46SDimitry Andric 
290d8e91e46SDimitry Andric   StringRef BaseTypeName;
291d8e91e46SDimitry Andric   Node = Func->getMetadata("kernel_arg_base_type");
292d8e91e46SDimitry Andric   if (Node && ArgNo < Node->getNumOperands())
293d8e91e46SDimitry Andric     BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
294d8e91e46SDimitry Andric 
295b1c73532SDimitry Andric   StringRef ActAccQual;
296b1c73532SDimitry Andric   // Do we really need NoAlias check here?
297b1c73532SDimitry Andric   if (Arg.getType()->isPointerTy() && Arg.hasNoAliasAttr()) {
298b1c73532SDimitry Andric     if (Arg.onlyReadsMemory())
299b1c73532SDimitry Andric       ActAccQual = "read_only";
300b1c73532SDimitry Andric     else if (Arg.hasAttribute(Attribute::WriteOnly))
301b1c73532SDimitry Andric       ActAccQual = "write_only";
302b1c73532SDimitry Andric   }
303b1c73532SDimitry Andric 
304d8e91e46SDimitry Andric   StringRef AccQual;
305d8e91e46SDimitry Andric   Node = Func->getMetadata("kernel_arg_access_qual");
306d8e91e46SDimitry Andric   if (Node && ArgNo < Node->getNumOperands())
307d8e91e46SDimitry Andric     AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
308d8e91e46SDimitry Andric 
309d8e91e46SDimitry Andric   StringRef TypeQual;
310d8e91e46SDimitry Andric   Node = Func->getMetadata("kernel_arg_type_qual");
311d8e91e46SDimitry Andric   if (Node && ArgNo < Node->getNumOperands())
312d8e91e46SDimitry Andric     TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
313d8e91e46SDimitry Andric 
314ac9a064cSDimitry Andric   const DataLayout &DL = Func->getDataLayout();
315d8e91e46SDimitry Andric 
316cfca06d7SDimitry Andric   MaybeAlign PointeeAlign;
317b60736ecSDimitry Andric   Type *Ty = Arg.hasByRefAttr() ? Arg.getParamByRefType() : Arg.getType();
318b60736ecSDimitry Andric 
319b60736ecSDimitry Andric   // FIXME: Need to distinguish in memory alignment from pointer alignment.
320d8e91e46SDimitry Andric   if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
3216f8fc217SDimitry Andric     if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS)
3226f8fc217SDimitry Andric       PointeeAlign = Arg.getParamAlign().valueOrOne();
323d8e91e46SDimitry Andric   }
324d8e91e46SDimitry Andric 
325b60736ecSDimitry Andric   // There's no distinction between byval aggregates and raw aggregates.
326b60736ecSDimitry Andric   Type *ArgTy;
327b60736ecSDimitry Andric   Align ArgAlign;
328b60736ecSDimitry Andric   std::tie(ArgTy, ArgAlign) = getArgumentTypeAlign(Arg, DL);
329b60736ecSDimitry Andric 
330b60736ecSDimitry Andric   emitKernelArg(DL, ArgTy, ArgAlign,
331b60736ecSDimitry Andric                 getValueKind(ArgTy, TypeQual, BaseTypeName), Offset, Args,
332b1c73532SDimitry Andric                 PointeeAlign, Name, TypeName, BaseTypeName, ActAccQual,
333b1c73532SDimitry Andric                 AccQual, TypeQual);
334d8e91e46SDimitry Andric }
335d8e91e46SDimitry Andric 
emitKernelArg(const DataLayout & DL,Type * Ty,Align Alignment,StringRef ValueKind,unsigned & Offset,msgpack::ArrayDocNode Args,MaybeAlign PointeeAlign,StringRef Name,StringRef TypeName,StringRef BaseTypeName,StringRef ActAccQual,StringRef AccQual,StringRef TypeQual)336b1c73532SDimitry Andric void MetadataStreamerMsgPackV4::emitKernelArg(
337b60736ecSDimitry Andric     const DataLayout &DL, Type *Ty, Align Alignment, StringRef ValueKind,
338b60736ecSDimitry Andric     unsigned &Offset, msgpack::ArrayDocNode Args, MaybeAlign PointeeAlign,
339b60736ecSDimitry Andric     StringRef Name, StringRef TypeName, StringRef BaseTypeName,
340b1c73532SDimitry Andric     StringRef ActAccQual, StringRef AccQual, StringRef TypeQual) {
341e6d15924SDimitry Andric   auto Arg = Args.getDocument()->getMapNode();
342d8e91e46SDimitry Andric 
343d8e91e46SDimitry Andric   if (!Name.empty())
344e6d15924SDimitry Andric     Arg[".name"] = Arg.getDocument()->getNode(Name, /*Copy=*/true);
345d8e91e46SDimitry Andric   if (!TypeName.empty())
346e6d15924SDimitry Andric     Arg[".type_name"] = Arg.getDocument()->getNode(TypeName, /*Copy=*/true);
347d8e91e46SDimitry Andric   auto Size = DL.getTypeAllocSize(Ty);
348e6d15924SDimitry Andric   Arg[".size"] = Arg.getDocument()->getNode(Size);
349cfca06d7SDimitry Andric   Offset = alignTo(Offset, Alignment);
350e6d15924SDimitry Andric   Arg[".offset"] = Arg.getDocument()->getNode(Offset);
351d8e91e46SDimitry Andric   Offset += Size;
352e6d15924SDimitry Andric   Arg[".value_kind"] = Arg.getDocument()->getNode(ValueKind, /*Copy=*/true);
353d8e91e46SDimitry Andric   if (PointeeAlign)
354cfca06d7SDimitry Andric     Arg[".pointee_align"] = Arg.getDocument()->getNode(PointeeAlign->value());
355d8e91e46SDimitry Andric 
356d8e91e46SDimitry Andric   if (auto PtrTy = dyn_cast<PointerType>(Ty))
357d8e91e46SDimitry Andric     if (auto Qualifier = getAddressSpaceQualifier(PtrTy->getAddressSpace()))
358e3b55780SDimitry Andric       // Limiting address space to emit only for a certain ValueKind.
359e3b55780SDimitry Andric       if (ValueKind == "global_buffer" || ValueKind == "dynamic_shared_pointer")
360e3b55780SDimitry Andric         Arg[".address_space"] = Arg.getDocument()->getNode(*Qualifier,
361e3b55780SDimitry Andric                                                            /*Copy=*/true);
362d8e91e46SDimitry Andric 
363d8e91e46SDimitry Andric   if (auto AQ = getAccessQualifier(AccQual))
364e6d15924SDimitry Andric     Arg[".access"] = Arg.getDocument()->getNode(*AQ, /*Copy=*/true);
365d8e91e46SDimitry Andric 
366b1c73532SDimitry Andric   if (auto AAQ = getAccessQualifier(ActAccQual))
367b1c73532SDimitry Andric     Arg[".actual_access"] = Arg.getDocument()->getNode(*AAQ, /*Copy=*/true);
368d8e91e46SDimitry Andric 
369d8e91e46SDimitry Andric   SmallVector<StringRef, 1> SplitTypeQuals;
370d8e91e46SDimitry Andric   TypeQual.split(SplitTypeQuals, " ", -1, false);
371d8e91e46SDimitry Andric   for (StringRef Key : SplitTypeQuals) {
372d8e91e46SDimitry Andric     if (Key == "const")
373e6d15924SDimitry Andric       Arg[".is_const"] = Arg.getDocument()->getNode(true);
374d8e91e46SDimitry Andric     else if (Key == "restrict")
375e6d15924SDimitry Andric       Arg[".is_restrict"] = Arg.getDocument()->getNode(true);
376d8e91e46SDimitry Andric     else if (Key == "volatile")
377e6d15924SDimitry Andric       Arg[".is_volatile"] = Arg.getDocument()->getNode(true);
378d8e91e46SDimitry Andric     else if (Key == "pipe")
379e6d15924SDimitry Andric       Arg[".is_pipe"] = Arg.getDocument()->getNode(true);
380d8e91e46SDimitry Andric   }
381d8e91e46SDimitry Andric 
382e6d15924SDimitry Andric   Args.push_back(Arg);
383d8e91e46SDimitry Andric }
384d8e91e46SDimitry Andric 
emitHiddenKernelArgs(const MachineFunction & MF,unsigned & Offset,msgpack::ArrayDocNode Args)385b1c73532SDimitry Andric void MetadataStreamerMsgPackV4::emitHiddenKernelArgs(
386e3b55780SDimitry Andric     const MachineFunction &MF, unsigned &Offset, msgpack::ArrayDocNode Args) {
387ecbca9f5SDimitry Andric   auto &Func = MF.getFunction();
388ecbca9f5SDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
389ecbca9f5SDimitry Andric 
39077fc4c14SDimitry Andric   unsigned HiddenArgNumBytes = ST.getImplicitArgNumBytes(Func);
391d8e91e46SDimitry Andric   if (!HiddenArgNumBytes)
392d8e91e46SDimitry Andric     return;
393d8e91e46SDimitry Andric 
394c0981da4SDimitry Andric   const Module *M = Func.getParent();
395c0981da4SDimitry Andric   auto &DL = M->getDataLayout();
396d8e91e46SDimitry Andric   auto Int64Ty = Type::getInt64Ty(Func.getContext());
397d8e91e46SDimitry Andric 
398145449b1SDimitry Andric   Offset = alignTo(Offset, ST.getAlignmentForImplicitArgPtr());
399145449b1SDimitry Andric 
400d8e91e46SDimitry Andric   if (HiddenArgNumBytes >= 8)
401b60736ecSDimitry Andric     emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset,
402b60736ecSDimitry Andric                   Args);
403d8e91e46SDimitry Andric   if (HiddenArgNumBytes >= 16)
404b60736ecSDimitry Andric     emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset,
405b60736ecSDimitry Andric                   Args);
406d8e91e46SDimitry Andric   if (HiddenArgNumBytes >= 24)
407b60736ecSDimitry Andric     emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset,
408b60736ecSDimitry Andric                   Args);
409d8e91e46SDimitry Andric 
410d8e91e46SDimitry Andric   auto Int8PtrTy =
411b1c73532SDimitry Andric       PointerType::get(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
412d8e91e46SDimitry Andric 
413d8e91e46SDimitry Andric   if (HiddenArgNumBytes >= 32) {
414145449b1SDimitry Andric     // We forbid the use of features requiring hostcall when compiling OpenCL
415145449b1SDimitry Andric     // before code object V5, which makes the mutual exclusion between the
416145449b1SDimitry Andric     // "printf buffer" and "hostcall buffer" here sound.
417c0981da4SDimitry Andric     if (M->getNamedMetadata("llvm.printf.fmts"))
418b60736ecSDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset,
419b60736ecSDimitry Andric                     Args);
420145449b1SDimitry Andric     else if (!Func.hasFnAttribute("amdgpu-no-hostcall-ptr"))
421b60736ecSDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset,
422b60736ecSDimitry Andric                     Args);
423145449b1SDimitry Andric     else
424b60736ecSDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
425d8e91e46SDimitry Andric   }
426d8e91e46SDimitry Andric 
427d8e91e46SDimitry Andric   // Emit "default queue" and "completion action" arguments if enqueue kernel is
428d8e91e46SDimitry Andric   // used, otherwise emit dummy "none" arguments.
429e3b55780SDimitry Andric   if (HiddenArgNumBytes >= 40) {
430e3b55780SDimitry Andric     if (!Func.hasFnAttribute("amdgpu-no-default-queue")) {
431b60736ecSDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset,
432b60736ecSDimitry Andric                     Args);
433d8e91e46SDimitry Andric     } else {
434b60736ecSDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
435e3b55780SDimitry Andric     }
436e3b55780SDimitry Andric   }
437e3b55780SDimitry Andric 
438e3b55780SDimitry Andric   if (HiddenArgNumBytes >= 48) {
4397fa27ce4SDimitry Andric     if (!Func.hasFnAttribute("amdgpu-no-completion-action")) {
440e3b55780SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset,
441e3b55780SDimitry Andric                     Args);
442e3b55780SDimitry Andric     } else {
443b60736ecSDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
444d8e91e46SDimitry Andric     }
445d8e91e46SDimitry Andric   }
446e6d15924SDimitry Andric 
447e6d15924SDimitry Andric   // Emit the pointer argument for multi-grid object.
448145449b1SDimitry Andric   if (HiddenArgNumBytes >= 56) {
449145449b1SDimitry Andric     if (!Func.hasFnAttribute("amdgpu-no-multigrid-sync-arg")) {
450b60736ecSDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset,
451b60736ecSDimitry Andric                     Args);
452145449b1SDimitry Andric     } else {
453145449b1SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
454145449b1SDimitry Andric     }
455145449b1SDimitry Andric   }
456d8e91e46SDimitry Andric }
457d8e91e46SDimitry Andric 
458b1c73532SDimitry Andric msgpack::MapDocNode
getHSAKernelProps(const MachineFunction & MF,const SIProgramInfo & ProgramInfo,unsigned CodeObjectVersion) const459b1c73532SDimitry Andric MetadataStreamerMsgPackV4::getHSAKernelProps(const MachineFunction &MF,
460b1c73532SDimitry Andric                                              const SIProgramInfo &ProgramInfo,
4617fa27ce4SDimitry Andric                                              unsigned CodeObjectVersion) const {
462d8e91e46SDimitry Andric   const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
463d8e91e46SDimitry Andric   const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
464d8e91e46SDimitry Andric   const Function &F = MF.getFunction();
465d8e91e46SDimitry Andric 
466e6d15924SDimitry Andric   auto Kern = HSAMetadataDoc->getMapNode();
467d8e91e46SDimitry Andric 
4681d5ae102SDimitry Andric   Align MaxKernArgAlign;
469e6d15924SDimitry Andric   Kern[".kernarg_segment_size"] = Kern.getDocument()->getNode(
470d8e91e46SDimitry Andric       STM.getKernArgSegmentSize(F, MaxKernArgAlign));
471d8e91e46SDimitry Andric   Kern[".group_segment_fixed_size"] =
472e6d15924SDimitry Andric       Kern.getDocument()->getNode(ProgramInfo.LDSSize);
473ac9a064cSDimitry Andric   DelayedExprs->assignDocNode(Kern[".private_segment_fixed_size"],
474ac9a064cSDimitry Andric                               msgpack::Type::UInt, ProgramInfo.ScratchSize);
475ac9a064cSDimitry Andric   if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5) {
476ac9a064cSDimitry Andric     DelayedExprs->assignDocNode(Kern[".uses_dynamic_stack"],
477ac9a064cSDimitry Andric                                 msgpack::Type::Boolean,
478ac9a064cSDimitry Andric                                 ProgramInfo.DynamicCallStack);
479ac9a064cSDimitry Andric   }
4807fa27ce4SDimitry Andric 
4817fa27ce4SDimitry Andric   if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5 && STM.supportsWGP())
482e3b55780SDimitry Andric     Kern[".workgroup_processor_mode"] =
483e3b55780SDimitry Andric         Kern.getDocument()->getNode(ProgramInfo.WgpMode);
484c0981da4SDimitry Andric 
485c0981da4SDimitry Andric   // FIXME: The metadata treats the minimum as 16?
486d8e91e46SDimitry Andric   Kern[".kernarg_segment_align"] =
4871d5ae102SDimitry Andric       Kern.getDocument()->getNode(std::max(Align(4), MaxKernArgAlign).value());
488d8e91e46SDimitry Andric   Kern[".wavefront_size"] =
489e6d15924SDimitry Andric       Kern.getDocument()->getNode(STM.getWavefrontSize());
490ac9a064cSDimitry Andric   DelayedExprs->assignDocNode(Kern[".sgpr_count"], msgpack::Type::UInt,
491ac9a064cSDimitry Andric                               ProgramInfo.NumSGPR);
492ac9a064cSDimitry Andric   DelayedExprs->assignDocNode(Kern[".vgpr_count"], msgpack::Type::UInt,
493ac9a064cSDimitry Andric                               ProgramInfo.NumVGPR);
494145449b1SDimitry Andric 
495145449b1SDimitry Andric   // Only add AGPR count to metadata for supported devices
496145449b1SDimitry Andric   if (STM.hasMAIInsts()) {
497ac9a064cSDimitry Andric     DelayedExprs->assignDocNode(Kern[".agpr_count"], msgpack::Type::UInt,
498ac9a064cSDimitry Andric                                 ProgramInfo.NumAccVGPR);
499145449b1SDimitry Andric   }
500145449b1SDimitry Andric 
501d8e91e46SDimitry Andric   Kern[".max_flat_workgroup_size"] =
502e6d15924SDimitry Andric       Kern.getDocument()->getNode(MFI.getMaxFlatWorkGroupSize());
503ac9a064cSDimitry Andric   unsigned NumWGX = MFI.getMaxNumWorkGroupsX();
504ac9a064cSDimitry Andric   unsigned NumWGY = MFI.getMaxNumWorkGroupsY();
505ac9a064cSDimitry Andric   unsigned NumWGZ = MFI.getMaxNumWorkGroupsZ();
506ac9a064cSDimitry Andric   if (NumWGX != 0 && NumWGY != 0 && NumWGZ != 0) {
507ac9a064cSDimitry Andric     Kern[".max_num_workgroups_x"] = Kern.getDocument()->getNode(NumWGX);
508ac9a064cSDimitry Andric     Kern[".max_num_workgroups_y"] = Kern.getDocument()->getNode(NumWGY);
509ac9a064cSDimitry Andric     Kern[".max_num_workgroups_z"] = Kern.getDocument()->getNode(NumWGZ);
510ac9a064cSDimitry Andric   }
511d8e91e46SDimitry Andric   Kern[".sgpr_spill_count"] =
512e6d15924SDimitry Andric       Kern.getDocument()->getNode(MFI.getNumSpilledSGPRs());
513d8e91e46SDimitry Andric   Kern[".vgpr_spill_count"] =
514e6d15924SDimitry Andric       Kern.getDocument()->getNode(MFI.getNumSpilledVGPRs());
515d8e91e46SDimitry Andric 
516e6d15924SDimitry Andric   return Kern;
517d8e91e46SDimitry Andric }
518d8e91e46SDimitry Andric 
emitTo(AMDGPUTargetStreamer & TargetStreamer)519b1c73532SDimitry Andric bool MetadataStreamerMsgPackV4::emitTo(AMDGPUTargetStreamer &TargetStreamer) {
520ac9a064cSDimitry Andric   DelayedExprs->resolveDelayedExpressions();
521e6d15924SDimitry Andric   return TargetStreamer.EmitHSAMetadata(*HSAMetadataDoc, true);
522d8e91e46SDimitry Andric }
523d8e91e46SDimitry Andric 
begin(const Module & Mod,const IsaInfo::AMDGPUTargetID & TargetID)524b1c73532SDimitry Andric void MetadataStreamerMsgPackV4::begin(const Module &Mod,
525344a3780SDimitry Andric                                       const IsaInfo::AMDGPUTargetID &TargetID) {
526d8e91e46SDimitry Andric   emitVersion();
527b1c73532SDimitry Andric   emitTargetID(TargetID);
528d8e91e46SDimitry Andric   emitPrintf(Mod);
529e6d15924SDimitry Andric   getRootMetadata("amdhsa.kernels") = HSAMetadataDoc->getArrayNode();
530ac9a064cSDimitry Andric   DelayedExprs->clear();
531d8e91e46SDimitry Andric }
532d8e91e46SDimitry Andric 
end()533b1c73532SDimitry Andric void MetadataStreamerMsgPackV4::end() {
534ac9a064cSDimitry Andric   DelayedExprs->resolveDelayedExpressions();
535d8e91e46SDimitry Andric   std::string HSAMetadataString;
536d8e91e46SDimitry Andric   raw_string_ostream StrOS(HSAMetadataString);
537e6d15924SDimitry Andric   HSAMetadataDoc->toYAML(StrOS);
538d8e91e46SDimitry Andric 
539d8e91e46SDimitry Andric   if (DumpHSAMetadata)
540d8e91e46SDimitry Andric     dump(StrOS.str());
541d8e91e46SDimitry Andric   if (VerifyHSAMetadata)
542d8e91e46SDimitry Andric     verify(StrOS.str());
543d8e91e46SDimitry Andric }
544d8e91e46SDimitry Andric 
emitKernel(const MachineFunction & MF,const SIProgramInfo & ProgramInfo)545b1c73532SDimitry Andric void MetadataStreamerMsgPackV4::emitKernel(const MachineFunction &MF,
546d8e91e46SDimitry Andric                                            const SIProgramInfo &ProgramInfo) {
547d8e91e46SDimitry Andric   auto &Func = MF.getFunction();
5487fa27ce4SDimitry Andric   if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL &&
5497fa27ce4SDimitry Andric       Func.getCallingConv() != CallingConv::SPIR_KERNEL)
5507fa27ce4SDimitry Andric     return;
551d8e91e46SDimitry Andric 
5524df029ccSDimitry Andric   auto CodeObjectVersion =
5534df029ccSDimitry Andric       AMDGPU::getAMDHSACodeObjectVersion(*Func.getParent());
5547fa27ce4SDimitry Andric   auto Kern = getHSAKernelProps(MF, ProgramInfo, CodeObjectVersion);
555d8e91e46SDimitry Andric 
556e6d15924SDimitry Andric   auto Kernels =
557e6d15924SDimitry Andric       getRootMetadata("amdhsa.kernels").getArray(/*Convert=*/true);
558d8e91e46SDimitry Andric 
559d8e91e46SDimitry Andric   {
560e6d15924SDimitry Andric     Kern[".name"] = Kern.getDocument()->getNode(Func.getName());
561e6d15924SDimitry Andric     Kern[".symbol"] = Kern.getDocument()->getNode(
562e6d15924SDimitry Andric         (Twine(Func.getName()) + Twine(".kd")).str(), /*Copy=*/true);
563d8e91e46SDimitry Andric     emitKernelLanguage(Func, Kern);
564d8e91e46SDimitry Andric     emitKernelAttrs(Func, Kern);
565ecbca9f5SDimitry Andric     emitKernelArgs(MF, Kern);
566d8e91e46SDimitry Andric   }
567d8e91e46SDimitry Andric 
568e6d15924SDimitry Andric   Kernels.push_back(Kern);
569d8e91e46SDimitry Andric }
570d8e91e46SDimitry Andric 
571344a3780SDimitry Andric //===----------------------------------------------------------------------===//
572ecbca9f5SDimitry Andric // HSAMetadataStreamerV5
573ecbca9f5SDimitry Andric //===----------------------------------------------------------------------===//
574ecbca9f5SDimitry Andric 
emitVersion()575e3b55780SDimitry Andric void MetadataStreamerMsgPackV5::emitVersion() {
576ecbca9f5SDimitry Andric   auto Version = HSAMetadataDoc->getArrayNode();
577ecbca9f5SDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMajorV5));
578ecbca9f5SDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMinorV5));
579ecbca9f5SDimitry Andric   getRootMetadata("amdhsa.version") = Version;
580ecbca9f5SDimitry Andric }
581ecbca9f5SDimitry Andric 
emitHiddenKernelArgs(const MachineFunction & MF,unsigned & Offset,msgpack::ArrayDocNode Args)582e3b55780SDimitry Andric void MetadataStreamerMsgPackV5::emitHiddenKernelArgs(
583e3b55780SDimitry Andric     const MachineFunction &MF, unsigned &Offset, msgpack::ArrayDocNode Args) {
584ecbca9f5SDimitry Andric   auto &Func = MF.getFunction();
585ecbca9f5SDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
586145449b1SDimitry Andric 
587145449b1SDimitry Andric   // No implicit kernel argument is used.
588145449b1SDimitry Andric   if (ST.getImplicitArgNumBytes(Func) == 0)
589145449b1SDimitry Andric     return;
590145449b1SDimitry Andric 
591ecbca9f5SDimitry Andric   const Module *M = Func.getParent();
592ecbca9f5SDimitry Andric   auto &DL = M->getDataLayout();
593145449b1SDimitry Andric   const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
594ecbca9f5SDimitry Andric 
595ecbca9f5SDimitry Andric   auto Int64Ty = Type::getInt64Ty(Func.getContext());
596ecbca9f5SDimitry Andric   auto Int32Ty = Type::getInt32Ty(Func.getContext());
597ecbca9f5SDimitry Andric   auto Int16Ty = Type::getInt16Ty(Func.getContext());
598ecbca9f5SDimitry Andric 
599145449b1SDimitry Andric   Offset = alignTo(Offset, ST.getAlignmentForImplicitArgPtr());
600ecbca9f5SDimitry Andric   emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_x", Offset, Args);
601ecbca9f5SDimitry Andric   emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_y", Offset, Args);
602ecbca9f5SDimitry Andric   emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_z", Offset, Args);
603ecbca9f5SDimitry Andric 
604ecbca9f5SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_x", Offset, Args);
605ecbca9f5SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_y", Offset, Args);
606ecbca9f5SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_z", Offset, Args);
607ecbca9f5SDimitry Andric 
608ecbca9f5SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_x", Offset, Args);
609ecbca9f5SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_y", Offset, Args);
610ecbca9f5SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_z", Offset, Args);
611ecbca9f5SDimitry Andric 
612ecbca9f5SDimitry Andric   // Reserved for hidden_tool_correlation_id.
613ecbca9f5SDimitry Andric   Offset += 8;
614ecbca9f5SDimitry Andric 
615ecbca9f5SDimitry Andric   Offset += 8; // Reserved.
616ecbca9f5SDimitry Andric 
617ecbca9f5SDimitry Andric   emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset, Args);
618ecbca9f5SDimitry Andric   emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset, Args);
619ecbca9f5SDimitry Andric   emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset, Args);
620ecbca9f5SDimitry Andric 
621ecbca9f5SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_grid_dims", Offset, Args);
622ecbca9f5SDimitry Andric 
623ecbca9f5SDimitry Andric   Offset += 6; // Reserved.
624ecbca9f5SDimitry Andric   auto Int8PtrTy =
625b1c73532SDimitry Andric       PointerType::get(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
626ecbca9f5SDimitry Andric 
627ecbca9f5SDimitry Andric   if (M->getNamedMetadata("llvm.printf.fmts")) {
628ecbca9f5SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset,
629ecbca9f5SDimitry Andric                   Args);
630145449b1SDimitry Andric   } else {
631ecbca9f5SDimitry Andric     Offset += 8; // Skipped.
632145449b1SDimitry Andric   }
633ecbca9f5SDimitry Andric 
634145449b1SDimitry Andric   if (!Func.hasFnAttribute("amdgpu-no-hostcall-ptr")) {
635ecbca9f5SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset,
636ecbca9f5SDimitry Andric                   Args);
637145449b1SDimitry Andric   } else {
638ecbca9f5SDimitry Andric     Offset += 8; // Skipped.
639145449b1SDimitry Andric   }
640ecbca9f5SDimitry Andric 
641145449b1SDimitry Andric   if (!Func.hasFnAttribute("amdgpu-no-multigrid-sync-arg")) {
642ecbca9f5SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset,
643ecbca9f5SDimitry Andric                 Args);
644145449b1SDimitry Andric   } else {
645145449b1SDimitry Andric     Offset += 8; // Skipped.
646145449b1SDimitry Andric   }
647ecbca9f5SDimitry Andric 
648145449b1SDimitry Andric   if (!Func.hasFnAttribute("amdgpu-no-heap-ptr"))
649145449b1SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_heap_v1", Offset, Args);
650145449b1SDimitry Andric   else
651145449b1SDimitry Andric     Offset += 8; // Skipped.
652ecbca9f5SDimitry Andric 
653e3b55780SDimitry Andric   if (!Func.hasFnAttribute("amdgpu-no-default-queue")) {
654ecbca9f5SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset,
655ecbca9f5SDimitry Andric                   Args);
656e3b55780SDimitry Andric   } else {
657e3b55780SDimitry Andric     Offset += 8; // Skipped.
658e3b55780SDimitry Andric   }
659e3b55780SDimitry Andric 
6607fa27ce4SDimitry Andric   if (!Func.hasFnAttribute("amdgpu-no-completion-action")) {
661ecbca9f5SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset,
662ecbca9f5SDimitry Andric                   Args);
663145449b1SDimitry Andric   } else {
664e3b55780SDimitry Andric     Offset += 8; // Skipped.
665145449b1SDimitry Andric   }
666ecbca9f5SDimitry Andric 
667aca2e42cSDimitry Andric   // Emit argument for hidden dynamic lds size
668aca2e42cSDimitry Andric   if (MFI.isDynamicLDSUsed()) {
669aca2e42cSDimitry Andric     emitKernelArg(DL, Int32Ty, Align(4), "hidden_dynamic_lds_size", Offset,
670aca2e42cSDimitry Andric                   Args);
671aca2e42cSDimitry Andric   } else {
672aca2e42cSDimitry Andric     Offset += 4; // skipped
673aca2e42cSDimitry Andric   }
674aca2e42cSDimitry Andric 
675aca2e42cSDimitry Andric   Offset += 68; // Reserved.
676ecbca9f5SDimitry Andric 
677145449b1SDimitry Andric   // hidden_private_base and hidden_shared_base are only when the subtarget has
678145449b1SDimitry Andric   // ApertureRegs.
679145449b1SDimitry Andric   if (!ST.hasApertureRegs()) {
680ecbca9f5SDimitry Andric     emitKernelArg(DL, Int32Ty, Align(4), "hidden_private_base", Offset, Args);
681ecbca9f5SDimitry Andric     emitKernelArg(DL, Int32Ty, Align(4), "hidden_shared_base", Offset, Args);
682145449b1SDimitry Andric   } else {
683ecbca9f5SDimitry Andric     Offset += 8; // Skipped.
684145449b1SDimitry Andric   }
685ecbca9f5SDimitry Andric 
686b1c73532SDimitry Andric   if (MFI.getUserSGPRInfo().hasQueuePtr())
687ecbca9f5SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_queue_ptr", Offset, Args);
688ecbca9f5SDimitry Andric }
689ecbca9f5SDimitry Andric 
emitKernelAttrs(const Function & Func,msgpack::MapDocNode Kern)690e3b55780SDimitry Andric void MetadataStreamerMsgPackV5::emitKernelAttrs(const Function &Func,
691e3b55780SDimitry Andric                                                 msgpack::MapDocNode Kern) {
692b1c73532SDimitry Andric   MetadataStreamerMsgPackV4::emitKernelAttrs(Func, Kern);
693e3b55780SDimitry Andric 
694e3b55780SDimitry Andric   if (Func.getFnAttribute("uniform-work-group-size").getValueAsBool())
695e3b55780SDimitry Andric     Kern[".uniform_work_group_size"] = Kern.getDocument()->getNode(1);
696e3b55780SDimitry Andric }
697e3b55780SDimitry Andric 
698ac9a064cSDimitry Andric //===----------------------------------------------------------------------===//
699ac9a064cSDimitry Andric // HSAMetadataStreamerV6
700ac9a064cSDimitry Andric //===----------------------------------------------------------------------===//
701e3b55780SDimitry Andric 
emitVersion()702ac9a064cSDimitry Andric void MetadataStreamerMsgPackV6::emitVersion() {
703ac9a064cSDimitry Andric   auto Version = HSAMetadataDoc->getArrayNode();
704ac9a064cSDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMajorV6));
705ac9a064cSDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMinorV6));
706ac9a064cSDimitry Andric   getRootMetadata("amdhsa.version") = Version;
707ac9a064cSDimitry Andric }
708ac9a064cSDimitry Andric 
709ac9a064cSDimitry Andric } // end namespace AMDGPU::HSAMD
71071d5a254SDimitry Andric } // end namespace llvm
711