101ce144dSScott Linder //===--- AMDGPUHSAMetadataStreamer.cpp --------------------------*- C++ -*-===//
201ce144dSScott Linder //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
601ce144dSScott Linder //
701ce144dSScott Linder //===----------------------------------------------------------------------===//
801ce144dSScott Linder //
901ce144dSScott Linder /// \file
1001ce144dSScott Linder /// AMDGPU HSA Metadata Streamer.
1101ce144dSScott Linder ///
1201ce144dSScott Linder //
1301ce144dSScott Linder //===----------------------------------------------------------------------===//
1401ce144dSScott Linder 
1501ce144dSScott Linder #include "AMDGPUHSAMetadataStreamer.h"
1601ce144dSScott Linder #include "AMDGPU.h"
17560d7e04Sdfukalov #include "GCNSubtarget.h"
18f5b36e56SScott Linder #include "MCTargetDesc/AMDGPUTargetStreamer.h"
1901ce144dSScott Linder #include "SIMachineFunctionInfo.h"
2001ce144dSScott Linder #include "SIProgramInfo.h"
2101ce144dSScott Linder #include "llvm/IR/Module.h"
221168119cSMatt Arsenault using namespace llvm;
231168119cSMatt Arsenault 
241168119cSMatt Arsenault static std::pair<Type *, Align> getArgumentTypeAlign(const Argument &Arg,
251168119cSMatt Arsenault                                                      const DataLayout &DL) {
261168119cSMatt Arsenault   Type *Ty = Arg.getType();
271168119cSMatt Arsenault   MaybeAlign ArgAlign;
281168119cSMatt Arsenault   if (Arg.hasByRefAttr()) {
291168119cSMatt Arsenault     Ty = Arg.getParamByRefType();
301168119cSMatt Arsenault     ArgAlign = Arg.getParamAlign();
311168119cSMatt Arsenault   }
321168119cSMatt Arsenault 
331168119cSMatt Arsenault   if (!ArgAlign)
341168119cSMatt Arsenault     ArgAlign = DL.getABITypeAlign(Ty);
351168119cSMatt Arsenault 
361168119cSMatt Arsenault   return std::make_pair(Ty, *ArgAlign);
371168119cSMatt Arsenault }
381168119cSMatt Arsenault 
3901ce144dSScott Linder namespace llvm {
4001ce144dSScott Linder 
4101ce144dSScott Linder static cl::opt<bool> DumpHSAMetadata(
4201ce144dSScott Linder     "amdgpu-dump-hsa-metadata",
4301ce144dSScott Linder     cl::desc("Dump AMDGPU HSA Metadata"));
4401ce144dSScott Linder static cl::opt<bool> VerifyHSAMetadata(
4501ce144dSScott Linder     "amdgpu-verify-hsa-metadata",
4601ce144dSScott Linder     cl::desc("Verify AMDGPU HSA Metadata"));
4701ce144dSScott Linder 
4801ce144dSScott Linder namespace AMDGPU {
4901ce144dSScott Linder namespace HSAMD {
5001ce144dSScott Linder 
51f5b36e56SScott Linder //===----------------------------------------------------------------------===//
52f5b36e56SScott Linder // HSAMetadataStreamerV2
53f5b36e56SScott Linder //===----------------------------------------------------------------------===//
54f5b36e56SScott Linder void MetadataStreamerV2::dump(StringRef HSAMetadataString) const {
5501ce144dSScott Linder   errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
5601ce144dSScott Linder }
5701ce144dSScott Linder 
58f5b36e56SScott Linder void MetadataStreamerV2::verify(StringRef HSAMetadataString) const {
5901ce144dSScott Linder   errs() << "AMDGPU HSA Metadata Parser Test: ";
6001ce144dSScott Linder 
6101ce144dSScott Linder   HSAMD::Metadata FromHSAMetadataString;
62f82cff31SSimon Pilgrim   if (fromString(HSAMetadataString, FromHSAMetadataString)) {
6301ce144dSScott Linder     errs() << "FAIL\n";
6401ce144dSScott Linder     return;
6501ce144dSScott Linder   }
6601ce144dSScott Linder 
6701ce144dSScott Linder   std::string ToHSAMetadataString;
6801ce144dSScott Linder   if (toString(FromHSAMetadataString, ToHSAMetadataString)) {
6901ce144dSScott Linder     errs() << "FAIL\n";
7001ce144dSScott Linder     return;
7101ce144dSScott Linder   }
7201ce144dSScott Linder 
7301ce144dSScott Linder   errs() << (HSAMetadataString == ToHSAMetadataString ? "PASS" : "FAIL")
7401ce144dSScott Linder          << '\n';
7501ce144dSScott Linder   if (HSAMetadataString != ToHSAMetadataString) {
7601ce144dSScott Linder     errs() << "Original input: " << HSAMetadataString << '\n'
7701ce144dSScott Linder            << "Produced output: " << ToHSAMetadataString << '\n';
7801ce144dSScott Linder   }
7901ce144dSScott Linder }
8001ce144dSScott Linder 
81f5b36e56SScott Linder AccessQualifier
82f5b36e56SScott Linder MetadataStreamerV2::getAccessQualifier(StringRef AccQual) const {
8301ce144dSScott Linder   if (AccQual.empty())
8401ce144dSScott Linder     return AccessQualifier::Unknown;
8501ce144dSScott Linder 
8601ce144dSScott Linder   return StringSwitch<AccessQualifier>(AccQual)
8701ce144dSScott Linder              .Case("read_only",  AccessQualifier::ReadOnly)
8801ce144dSScott Linder              .Case("write_only", AccessQualifier::WriteOnly)
8901ce144dSScott Linder              .Case("read_write", AccessQualifier::ReadWrite)
9001ce144dSScott Linder              .Default(AccessQualifier::Default);
9101ce144dSScott Linder }
9201ce144dSScott Linder 
93f5b36e56SScott Linder AddressSpaceQualifier
94f5b36e56SScott Linder MetadataStreamerV2::getAddressSpaceQualifier(
9501ce144dSScott Linder     unsigned AddressSpace) const {
96b9986746SMatt Arsenault   switch (AddressSpace) {
97b9986746SMatt Arsenault   case AMDGPUAS::PRIVATE_ADDRESS:
9801ce144dSScott Linder     return AddressSpaceQualifier::Private;
99b9986746SMatt Arsenault   case AMDGPUAS::GLOBAL_ADDRESS:
10001ce144dSScott Linder     return AddressSpaceQualifier::Global;
101b9986746SMatt Arsenault   case AMDGPUAS::CONSTANT_ADDRESS:
10201ce144dSScott Linder     return AddressSpaceQualifier::Constant;
103b9986746SMatt Arsenault   case AMDGPUAS::LOCAL_ADDRESS:
10401ce144dSScott Linder     return AddressSpaceQualifier::Local;
105b9986746SMatt Arsenault   case AMDGPUAS::FLAT_ADDRESS:
10601ce144dSScott Linder     return AddressSpaceQualifier::Generic;
107b9986746SMatt Arsenault   case AMDGPUAS::REGION_ADDRESS:
10801ce144dSScott Linder     return AddressSpaceQualifier::Region;
109b9986746SMatt Arsenault   default:
110b9986746SMatt Arsenault     return AddressSpaceQualifier::Unknown;
111b9986746SMatt Arsenault   }
11201ce144dSScott Linder }
11301ce144dSScott Linder 
114f5b36e56SScott Linder ValueKind MetadataStreamerV2::getValueKind(Type *Ty, StringRef TypeQual,
11501ce144dSScott Linder                                            StringRef BaseTypeName) const {
1166fe949c4SKazu Hirata   if (TypeQual.contains("pipe"))
11701ce144dSScott Linder     return ValueKind::Pipe;
11801ce144dSScott Linder 
11901ce144dSScott Linder   return StringSwitch<ValueKind>(BaseTypeName)
12001ce144dSScott Linder              .Case("image1d_t", ValueKind::Image)
12101ce144dSScott Linder              .Case("image1d_array_t", ValueKind::Image)
12201ce144dSScott Linder              .Case("image1d_buffer_t", ValueKind::Image)
12301ce144dSScott Linder              .Case("image2d_t", ValueKind::Image)
12401ce144dSScott Linder              .Case("image2d_array_t", ValueKind::Image)
12501ce144dSScott Linder              .Case("image2d_array_depth_t", ValueKind::Image)
12601ce144dSScott Linder              .Case("image2d_array_msaa_t", ValueKind::Image)
12701ce144dSScott Linder              .Case("image2d_array_msaa_depth_t", ValueKind::Image)
12801ce144dSScott Linder              .Case("image2d_depth_t", ValueKind::Image)
12901ce144dSScott Linder              .Case("image2d_msaa_t", ValueKind::Image)
13001ce144dSScott Linder              .Case("image2d_msaa_depth_t", ValueKind::Image)
13101ce144dSScott Linder              .Case("image3d_t", ValueKind::Image)
13201ce144dSScott Linder              .Case("sampler_t", ValueKind::Sampler)
13301ce144dSScott Linder              .Case("queue_t", ValueKind::Queue)
13401ce144dSScott Linder              .Default(isa<PointerType>(Ty) ?
13501ce144dSScott Linder                           (Ty->getPointerAddressSpace() ==
1360da6350dSMatt Arsenault                            AMDGPUAS::LOCAL_ADDRESS ?
13701ce144dSScott Linder                            ValueKind::DynamicSharedPointer :
13801ce144dSScott Linder                            ValueKind::GlobalBuffer) :
13901ce144dSScott Linder                       ValueKind::ByValue);
14001ce144dSScott Linder }
14101ce144dSScott Linder 
142f5b36e56SScott Linder std::string MetadataStreamerV2::getTypeName(Type *Ty, bool Signed) const {
14301ce144dSScott Linder   switch (Ty->getTypeID()) {
14401ce144dSScott Linder   case Type::IntegerTyID: {
14501ce144dSScott Linder     if (!Signed)
14601ce144dSScott Linder       return (Twine('u') + getTypeName(Ty, true)).str();
14701ce144dSScott Linder 
14801ce144dSScott Linder     auto BitWidth = Ty->getIntegerBitWidth();
14901ce144dSScott Linder     switch (BitWidth) {
15001ce144dSScott Linder     case 8:
15101ce144dSScott Linder       return "char";
15201ce144dSScott Linder     case 16:
15301ce144dSScott Linder       return "short";
15401ce144dSScott Linder     case 32:
15501ce144dSScott Linder       return "int";
15601ce144dSScott Linder     case 64:
15701ce144dSScott Linder       return "long";
15801ce144dSScott Linder     default:
15901ce144dSScott Linder       return (Twine('i') + Twine(BitWidth)).str();
16001ce144dSScott Linder     }
16101ce144dSScott Linder   }
16201ce144dSScott Linder   case Type::HalfTyID:
16301ce144dSScott Linder     return "half";
16401ce144dSScott Linder   case Type::FloatTyID:
16501ce144dSScott Linder     return "float";
16601ce144dSScott Linder   case Type::DoubleTyID:
16701ce144dSScott Linder     return "double";
1682dea3f12SChristopher Tetreault   case Type::FixedVectorTyID: {
1693254a001SChristopher Tetreault     auto VecTy = cast<FixedVectorType>(Ty);
17001ce144dSScott Linder     auto ElTy = VecTy->getElementType();
171e634f482SChristopher Tetreault     auto NumElements = VecTy->getNumElements();
17201ce144dSScott Linder     return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
17301ce144dSScott Linder   }
17401ce144dSScott Linder   default:
17501ce144dSScott Linder     return "unknown";
17601ce144dSScott Linder   }
17701ce144dSScott Linder }
17801ce144dSScott Linder 
179f5b36e56SScott Linder std::vector<uint32_t>
180f5b36e56SScott Linder MetadataStreamerV2::getWorkGroupDimensions(MDNode *Node) const {
18101ce144dSScott Linder   std::vector<uint32_t> Dims;
18201ce144dSScott Linder   if (Node->getNumOperands() != 3)
18301ce144dSScott Linder     return Dims;
18401ce144dSScott Linder 
18501ce144dSScott Linder   for (auto &Op : Node->operands())
18601ce144dSScott Linder     Dims.push_back(mdconst::extract<ConstantInt>(Op)->getZExtValue());
18701ce144dSScott Linder   return Dims;
18801ce144dSScott Linder }
18901ce144dSScott Linder 
190f5b36e56SScott Linder Kernel::CodeProps::Metadata
191f5b36e56SScott Linder MetadataStreamerV2::getHSACodeProps(const MachineFunction &MF,
19201ce144dSScott Linder                                     const SIProgramInfo &ProgramInfo) const {
1935bfbae5cSTom Stellard   const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
19401ce144dSScott Linder   const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
19501ce144dSScott Linder   HSAMD::Kernel::CodeProps::Metadata HSACodeProps;
19601ce144dSScott Linder   const Function &F = MF.getFunction();
19701ce144dSScott Linder 
1984bec7d42SMatt Arsenault   assert(F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
1994bec7d42SMatt Arsenault          F.getCallingConv() == CallingConv::SPIR_KERNEL);
20001ce144dSScott Linder 
201b65fa483SGuillaume Chatelet   Align MaxKernArgAlign;
2024bec7d42SMatt Arsenault   HSACodeProps.mKernargSegmentSize = STM.getKernArgSegmentSize(F,
2034bec7d42SMatt Arsenault                                                                MaxKernArgAlign);
204b65fa483SGuillaume Chatelet   HSACodeProps.mKernargSegmentAlign =
205b65fa483SGuillaume Chatelet     std::max(MaxKernArgAlign, Align(4)).value();
20690ff1487SMatt Arsenault 
20790ff1487SMatt Arsenault   HSACodeProps.mGroupSegmentFixedSize = ProgramInfo.LDSSize;
20890ff1487SMatt Arsenault   HSACodeProps.mPrivateSegmentFixedSize = ProgramInfo.ScratchSize;
20901ce144dSScott Linder   HSACodeProps.mWavefrontSize = STM.getWavefrontSize();
21001ce144dSScott Linder   HSACodeProps.mNumSGPRs = ProgramInfo.NumSGPR;
21101ce144dSScott Linder   HSACodeProps.mNumVGPRs = ProgramInfo.NumVGPR;
21201ce144dSScott Linder   HSACodeProps.mMaxFlatWorkGroupSize = MFI.getMaxFlatWorkGroupSize();
21301ce144dSScott Linder   HSACodeProps.mIsDynamicCallStack = ProgramInfo.DynamicCallStack;
21401ce144dSScott Linder   HSACodeProps.mIsXNACKEnabled = STM.isXNACKEnabled();
21501ce144dSScott Linder   HSACodeProps.mNumSpilledSGPRs = MFI.getNumSpilledSGPRs();
21601ce144dSScott Linder   HSACodeProps.mNumSpilledVGPRs = MFI.getNumSpilledVGPRs();
21701ce144dSScott Linder 
21801ce144dSScott Linder   return HSACodeProps;
21901ce144dSScott Linder }
22001ce144dSScott Linder 
221f5b36e56SScott Linder Kernel::DebugProps::Metadata
222f5b36e56SScott Linder MetadataStreamerV2::getHSADebugProps(const MachineFunction &MF,
22301ce144dSScott Linder                                      const SIProgramInfo &ProgramInfo) const {
224aa6fb4c4SMatt Arsenault   return HSAMD::Kernel::DebugProps::Metadata();
22501ce144dSScott Linder }
22601ce144dSScott Linder 
227f5b36e56SScott Linder void MetadataStreamerV2::emitVersion() {
22801ce144dSScott Linder   auto &Version = HSAMetadata.mVersion;
22901ce144dSScott Linder 
230f4ace637SKonstantin Zhuravlyov   Version.push_back(VersionMajorV2);
231f4ace637SKonstantin Zhuravlyov   Version.push_back(VersionMinorV2);
23201ce144dSScott Linder }
23301ce144dSScott Linder 
234f5b36e56SScott Linder void MetadataStreamerV2::emitPrintf(const Module &Mod) {
23501ce144dSScott Linder   auto &Printf = HSAMetadata.mPrintf;
23601ce144dSScott Linder 
23701ce144dSScott Linder   auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
23801ce144dSScott Linder   if (!Node)
23901ce144dSScott Linder     return;
24001ce144dSScott Linder 
24101ce144dSScott Linder   for (auto Op : Node->operands())
24201ce144dSScott Linder     if (Op->getNumOperands())
243adcd0268SBenjamin Kramer       Printf.push_back(
244adcd0268SBenjamin Kramer           std::string(cast<MDString>(Op->getOperand(0))->getString()));
24501ce144dSScott Linder }
24601ce144dSScott Linder 
247f5b36e56SScott Linder void MetadataStreamerV2::emitKernelLanguage(const Function &Func) {
24801ce144dSScott Linder   auto &Kernel = HSAMetadata.mKernels.back();
24901ce144dSScott Linder 
25001ce144dSScott Linder   // TODO: What about other languages?
25101ce144dSScott Linder   auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
25201ce144dSScott Linder   if (!Node || !Node->getNumOperands())
25301ce144dSScott Linder     return;
25401ce144dSScott Linder   auto Op0 = Node->getOperand(0);
25501ce144dSScott Linder   if (Op0->getNumOperands() <= 1)
25601ce144dSScott Linder     return;
25701ce144dSScott Linder 
25801ce144dSScott Linder   Kernel.mLanguage = "OpenCL C";
25901ce144dSScott Linder   Kernel.mLanguageVersion.push_back(
26001ce144dSScott Linder       mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue());
26101ce144dSScott Linder   Kernel.mLanguageVersion.push_back(
26201ce144dSScott Linder       mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue());
26301ce144dSScott Linder }
26401ce144dSScott Linder 
265f5b36e56SScott Linder void MetadataStreamerV2::emitKernelAttrs(const Function &Func) {
26601ce144dSScott Linder   auto &Attrs = HSAMetadata.mKernels.back().mAttrs;
26701ce144dSScott Linder 
26801ce144dSScott Linder   if (auto Node = Func.getMetadata("reqd_work_group_size"))
26901ce144dSScott Linder     Attrs.mReqdWorkGroupSize = getWorkGroupDimensions(Node);
27001ce144dSScott Linder   if (auto Node = Func.getMetadata("work_group_size_hint"))
27101ce144dSScott Linder     Attrs.mWorkGroupSizeHint = getWorkGroupDimensions(Node);
27201ce144dSScott Linder   if (auto Node = Func.getMetadata("vec_type_hint")) {
27301ce144dSScott Linder     Attrs.mVecTypeHint = getTypeName(
27401ce144dSScott Linder         cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
27501ce144dSScott Linder         mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue());
27601ce144dSScott Linder   }
27701ce144dSScott Linder   if (Func.hasFnAttribute("runtime-handle")) {
27801ce144dSScott Linder     Attrs.mRuntimeHandle =
27901ce144dSScott Linder         Func.getFnAttribute("runtime-handle").getValueAsString().str();
28001ce144dSScott Linder   }
28101ce144dSScott Linder }
28201ce144dSScott Linder 
283ae0ba7deSMatt Arsenault void MetadataStreamerV2::emitKernelArgs(const Function &Func,
284ae0ba7deSMatt Arsenault                                         const GCNSubtarget &ST) {
28501ce144dSScott Linder   for (auto &Arg : Func.args())
28601ce144dSScott Linder     emitKernelArg(Arg);
28701ce144dSScott Linder 
288ae0ba7deSMatt Arsenault   emitHiddenKernelArgs(Func, ST);
28901ce144dSScott Linder }
29001ce144dSScott Linder 
291f5b36e56SScott Linder void MetadataStreamerV2::emitKernelArg(const Argument &Arg) {
29201ce144dSScott Linder   auto Func = Arg.getParent();
29301ce144dSScott Linder   auto ArgNo = Arg.getArgNo();
29401ce144dSScott Linder   const MDNode *Node;
29501ce144dSScott Linder 
29601ce144dSScott Linder   StringRef Name;
29701ce144dSScott Linder   Node = Func->getMetadata("kernel_arg_name");
29801ce144dSScott Linder   if (Node && ArgNo < Node->getNumOperands())
29901ce144dSScott Linder     Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
30001ce144dSScott Linder   else if (Arg.hasName())
30101ce144dSScott Linder     Name = Arg.getName();
30201ce144dSScott Linder 
30301ce144dSScott Linder   StringRef TypeName;
30401ce144dSScott Linder   Node = Func->getMetadata("kernel_arg_type");
30501ce144dSScott Linder   if (Node && ArgNo < Node->getNumOperands())
30601ce144dSScott Linder     TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
30701ce144dSScott Linder 
30801ce144dSScott Linder   StringRef BaseTypeName;
30901ce144dSScott Linder   Node = Func->getMetadata("kernel_arg_base_type");
31001ce144dSScott Linder   if (Node && ArgNo < Node->getNumOperands())
31101ce144dSScott Linder     BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
31201ce144dSScott Linder 
31301ce144dSScott Linder   StringRef AccQual;
31401ce144dSScott Linder   if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() &&
31501ce144dSScott Linder       Arg.hasNoAliasAttr()) {
31601ce144dSScott Linder     AccQual = "read_only";
31701ce144dSScott Linder   } else {
31801ce144dSScott Linder     Node = Func->getMetadata("kernel_arg_access_qual");
31901ce144dSScott Linder     if (Node && ArgNo < Node->getNumOperands())
32001ce144dSScott Linder       AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
32101ce144dSScott Linder   }
32201ce144dSScott Linder 
32301ce144dSScott Linder   StringRef TypeQual;
32401ce144dSScott Linder   Node = Func->getMetadata("kernel_arg_type_qual");
32501ce144dSScott Linder   if (Node && ArgNo < Node->getNumOperands())
32601ce144dSScott Linder     TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
32701ce144dSScott Linder 
32801ce144dSScott Linder   const DataLayout &DL = Func->getParent()->getDataLayout();
32901ce144dSScott Linder 
330d3085c25SGuillaume Chatelet   MaybeAlign PointeeAlign;
3311168119cSMatt Arsenault   if (auto PtrTy = dyn_cast<PointerType>(Arg.getType())) {
3320da6350dSMatt Arsenault     if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
3331168119cSMatt Arsenault       // FIXME: Should report this for all address spaces
334a5e324e3SNikita Popov       PointeeAlign = Arg.getParamAlign().valueOrOne();
33501ce144dSScott Linder     }
33601ce144dSScott Linder   }
33701ce144dSScott Linder 
3381168119cSMatt Arsenault   Type *ArgTy;
3391168119cSMatt Arsenault   Align ArgAlign;
3401168119cSMatt Arsenault   std::tie(ArgTy, ArgAlign) = getArgumentTypeAlign(Arg, DL);
3411168119cSMatt Arsenault 
3421168119cSMatt Arsenault   emitKernelArg(DL, ArgTy, ArgAlign,
3431168119cSMatt Arsenault                 getValueKind(ArgTy, TypeQual, BaseTypeName), PointeeAlign, Name,
3441168119cSMatt Arsenault                 TypeName, BaseTypeName, AccQual, TypeQual);
34501ce144dSScott Linder }
34601ce144dSScott Linder 
347f5b36e56SScott Linder void MetadataStreamerV2::emitKernelArg(const DataLayout &DL, Type *Ty,
3481168119cSMatt Arsenault                                        Align Alignment, ValueKind ValueKind,
349d3085c25SGuillaume Chatelet                                        MaybeAlign PointeeAlign, StringRef Name,
350f5b36e56SScott Linder                                        StringRef TypeName,
351f5b36e56SScott Linder                                        StringRef BaseTypeName,
35201ce144dSScott Linder                                        StringRef AccQual, StringRef TypeQual) {
35301ce144dSScott Linder   HSAMetadata.mKernels.back().mArgs.push_back(Kernel::Arg::Metadata());
35401ce144dSScott Linder   auto &Arg = HSAMetadata.mKernels.back().mArgs.back();
35501ce144dSScott Linder 
356adcd0268SBenjamin Kramer   Arg.mName = std::string(Name);
357adcd0268SBenjamin Kramer   Arg.mTypeName = std::string(TypeName);
35801ce144dSScott Linder   Arg.mSize = DL.getTypeAllocSize(Ty);
3591168119cSMatt Arsenault   Arg.mAlign = Alignment.value();
36001ce144dSScott Linder   Arg.mValueKind = ValueKind;
361d3085c25SGuillaume Chatelet   Arg.mPointeeAlign = PointeeAlign ? PointeeAlign->value() : 0;
36201ce144dSScott Linder 
36301ce144dSScott Linder   if (auto PtrTy = dyn_cast<PointerType>(Ty))
364f5b36e56SScott Linder     Arg.mAddrSpaceQual = getAddressSpaceQualifier(PtrTy->getAddressSpace());
36501ce144dSScott Linder 
36601ce144dSScott Linder   Arg.mAccQual = getAccessQualifier(AccQual);
36701ce144dSScott Linder 
36801ce144dSScott Linder   // TODO: Emit Arg.mActualAccQual.
36901ce144dSScott Linder 
37001ce144dSScott Linder   SmallVector<StringRef, 1> SplitTypeQuals;
37101ce144dSScott Linder   TypeQual.split(SplitTypeQuals, " ", -1, false);
37201ce144dSScott Linder   for (StringRef Key : SplitTypeQuals) {
37301ce144dSScott Linder     auto P = StringSwitch<bool*>(Key)
37401ce144dSScott Linder                  .Case("const",    &Arg.mIsConst)
37501ce144dSScott Linder                  .Case("restrict", &Arg.mIsRestrict)
37601ce144dSScott Linder                  .Case("volatile", &Arg.mIsVolatile)
37701ce144dSScott Linder                  .Case("pipe",     &Arg.mIsPipe)
37801ce144dSScott Linder                  .Default(nullptr);
37901ce144dSScott Linder     if (P)
38001ce144dSScott Linder       *P = true;
38101ce144dSScott Linder   }
38201ce144dSScott Linder }
38301ce144dSScott Linder 
384ae0ba7deSMatt Arsenault void MetadataStreamerV2::emitHiddenKernelArgs(const Function &Func,
385ae0ba7deSMatt Arsenault                                               const GCNSubtarget &ST) {
386ae0ba7deSMatt Arsenault   unsigned HiddenArgNumBytes = ST.getImplicitArgNumBytes(Func);
38701ce144dSScott Linder   if (!HiddenArgNumBytes)
38801ce144dSScott Linder     return;
38901ce144dSScott Linder 
39001ce144dSScott Linder   auto &DL = Func.getParent()->getDataLayout();
39101ce144dSScott Linder   auto Int64Ty = Type::getInt64Ty(Func.getContext());
39201ce144dSScott Linder 
39301ce144dSScott Linder   if (HiddenArgNumBytes >= 8)
3941168119cSMatt Arsenault     emitKernelArg(DL, Int64Ty, Align(8), ValueKind::HiddenGlobalOffsetX);
39501ce144dSScott Linder   if (HiddenArgNumBytes >= 16)
3961168119cSMatt Arsenault     emitKernelArg(DL, Int64Ty, Align(8), ValueKind::HiddenGlobalOffsetY);
39701ce144dSScott Linder   if (HiddenArgNumBytes >= 24)
3981168119cSMatt Arsenault     emitKernelArg(DL, Int64Ty, Align(8), ValueKind::HiddenGlobalOffsetZ);
39901ce144dSScott Linder 
40001ce144dSScott Linder   auto Int8PtrTy = Type::getInt8PtrTy(Func.getContext(),
4010da6350dSMatt Arsenault                                       AMDGPUAS::GLOBAL_ADDRESS);
40201ce144dSScott Linder 
40301ce144dSScott Linder   // Emit "printf buffer" argument if printf is used, otherwise emit dummy
40401ce144dSScott Linder   // "none" argument.
40501ce144dSScott Linder   if (HiddenArgNumBytes >= 32) {
40601ce144dSScott Linder     if (Func.getParent()->getNamedMetadata("llvm.printf.fmts"))
4071168119cSMatt Arsenault       emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenPrintfBuffer);
408d8f99bb6SSameer Sahasrabuddhe     else if (!Func.hasFnAttribute("amdgpu-no-hostcall-ptr")) {
40952c5014dSSameer Sahasrabuddhe       // The printf runtime binding pass should have ensured that hostcall and
41052c5014dSSameer Sahasrabuddhe       // printf are not used in the same module.
41152c5014dSSameer Sahasrabuddhe       assert(!Func.getParent()->getNamedMetadata("llvm.printf.fmts"));
4121168119cSMatt Arsenault       emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenHostcallBuffer);
41352c5014dSSameer Sahasrabuddhe     } else
4141168119cSMatt Arsenault       emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenNone);
41501ce144dSScott Linder   }
41601ce144dSScott Linder 
41701ce144dSScott Linder   // Emit "default queue" and "completion action" arguments if enqueue kernel is
41801ce144dSScott Linder   // used, otherwise emit dummy "none" arguments.
41901ce144dSScott Linder   if (HiddenArgNumBytes >= 48) {
42001ce144dSScott Linder     if (Func.hasFnAttribute("calls-enqueue-kernel")) {
4211168119cSMatt Arsenault       emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenDefaultQueue);
4221168119cSMatt Arsenault       emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenCompletionAction);
42301ce144dSScott Linder     } else {
4241168119cSMatt Arsenault       emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenNone);
4251168119cSMatt Arsenault       emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenNone);
42601ce144dSScott Linder     }
42701ce144dSScott Linder   }
428a6241352SYaxun Liu 
429a6241352SYaxun Liu   // Emit the pointer argument for multi-grid object.
430a6241352SYaxun Liu   if (HiddenArgNumBytes >= 56)
4311168119cSMatt Arsenault     emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenMultiGridSyncArg);
43201ce144dSScott Linder }
43301ce144dSScott Linder 
434f5b36e56SScott Linder bool MetadataStreamerV2::emitTo(AMDGPUTargetStreamer &TargetStreamer) {
435f5b36e56SScott Linder   return TargetStreamer.EmitHSAMetadata(getHSAMetadata());
436f5b36e56SScott Linder }
437f5b36e56SScott Linder 
438f4ace637SKonstantin Zhuravlyov void MetadataStreamerV2::begin(const Module &Mod,
439f4ace637SKonstantin Zhuravlyov                                const IsaInfo::AMDGPUTargetID &TargetID) {
44001ce144dSScott Linder   emitVersion();
44101ce144dSScott Linder   emitPrintf(Mod);
44201ce144dSScott Linder }
44301ce144dSScott Linder 
444f5b36e56SScott Linder void MetadataStreamerV2::end() {
44501ce144dSScott Linder   std::string HSAMetadataString;
44601ce144dSScott Linder   if (toString(HSAMetadata, HSAMetadataString))
44701ce144dSScott Linder     return;
44801ce144dSScott Linder 
44901ce144dSScott Linder   if (DumpHSAMetadata)
45001ce144dSScott Linder     dump(HSAMetadataString);
45101ce144dSScott Linder   if (VerifyHSAMetadata)
45201ce144dSScott Linder     verify(HSAMetadataString);
45301ce144dSScott Linder }
45401ce144dSScott Linder 
455f5b36e56SScott Linder void MetadataStreamerV2::emitKernel(const MachineFunction &MF,
456f5b36e56SScott Linder                                     const SIProgramInfo &ProgramInfo) {
45701ce144dSScott Linder   auto &Func = MF.getFunction();
45801ce144dSScott Linder   if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL)
45901ce144dSScott Linder     return;
46001ce144dSScott Linder 
4614bec7d42SMatt Arsenault   auto CodeProps = getHSACodeProps(MF, ProgramInfo);
4624bec7d42SMatt Arsenault   auto DebugProps = getHSADebugProps(MF, ProgramInfo);
4634bec7d42SMatt Arsenault 
46401ce144dSScott Linder   HSAMetadata.mKernels.push_back(Kernel::Metadata());
46501ce144dSScott Linder   auto &Kernel = HSAMetadata.mKernels.back();
46601ce144dSScott Linder 
467ae0ba7deSMatt Arsenault   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
468adcd0268SBenjamin Kramer   Kernel.mName = std::string(Func.getName());
46901ce144dSScott Linder   Kernel.mSymbolName = (Twine(Func.getName()) + Twine("@kd")).str();
47001ce144dSScott Linder   emitKernelLanguage(Func);
47101ce144dSScott Linder   emitKernelAttrs(Func);
472ae0ba7deSMatt Arsenault   emitKernelArgs(Func, ST);
47301ce144dSScott Linder   HSAMetadata.mKernels.back().mCodeProps = CodeProps;
47401ce144dSScott Linder   HSAMetadata.mKernels.back().mDebugProps = DebugProps;
47501ce144dSScott Linder }
47601ce144dSScott Linder 
477f5b36e56SScott Linder //===----------------------------------------------------------------------===//
478f5b36e56SScott Linder // HSAMetadataStreamerV3
479f5b36e56SScott Linder //===----------------------------------------------------------------------===//
480f5b36e56SScott Linder 
481f5b36e56SScott Linder void MetadataStreamerV3::dump(StringRef HSAMetadataString) const {
482f5b36e56SScott Linder   errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
483f5b36e56SScott Linder }
484f5b36e56SScott Linder 
485f5b36e56SScott Linder void MetadataStreamerV3::verify(StringRef HSAMetadataString) const {
486f5b36e56SScott Linder   errs() << "AMDGPU HSA Metadata Parser Test: ";
487f5b36e56SScott Linder 
488ed0b9af9STim Renouf   msgpack::Document FromHSAMetadataString;
489f5b36e56SScott Linder 
490ed0b9af9STim Renouf   if (!FromHSAMetadataString.fromYAML(HSAMetadataString)) {
491f5b36e56SScott Linder     errs() << "FAIL\n";
492f5b36e56SScott Linder     return;
493f5b36e56SScott Linder   }
494f5b36e56SScott Linder 
495f5b36e56SScott Linder   std::string ToHSAMetadataString;
496f5b36e56SScott Linder   raw_string_ostream StrOS(ToHSAMetadataString);
497ed0b9af9STim Renouf   FromHSAMetadataString.toYAML(StrOS);
498f5b36e56SScott Linder 
499f5b36e56SScott Linder   errs() << (HSAMetadataString == StrOS.str() ? "PASS" : "FAIL") << '\n';
500f5b36e56SScott Linder   if (HSAMetadataString != ToHSAMetadataString) {
501f5b36e56SScott Linder     errs() << "Original input: " << HSAMetadataString << '\n'
502f5b36e56SScott Linder            << "Produced output: " << StrOS.str() << '\n';
503f5b36e56SScott Linder   }
504f5b36e56SScott Linder }
505f5b36e56SScott Linder 
506f5b36e56SScott Linder Optional<StringRef>
507f5b36e56SScott Linder MetadataStreamerV3::getAccessQualifier(StringRef AccQual) const {
508f5b36e56SScott Linder   return StringSwitch<Optional<StringRef>>(AccQual)
509f5b36e56SScott Linder       .Case("read_only", StringRef("read_only"))
510f5b36e56SScott Linder       .Case("write_only", StringRef("write_only"))
511f5b36e56SScott Linder       .Case("read_write", StringRef("read_write"))
512f5b36e56SScott Linder       .Default(None);
513f5b36e56SScott Linder }
514f5b36e56SScott Linder 
515f5b36e56SScott Linder Optional<StringRef>
516f5b36e56SScott Linder MetadataStreamerV3::getAddressSpaceQualifier(unsigned AddressSpace) const {
517f5b36e56SScott Linder   switch (AddressSpace) {
518f5b36e56SScott Linder   case AMDGPUAS::PRIVATE_ADDRESS:
519f5b36e56SScott Linder     return StringRef("private");
520f5b36e56SScott Linder   case AMDGPUAS::GLOBAL_ADDRESS:
521f5b36e56SScott Linder     return StringRef("global");
522f5b36e56SScott Linder   case AMDGPUAS::CONSTANT_ADDRESS:
523f5b36e56SScott Linder     return StringRef("constant");
524f5b36e56SScott Linder   case AMDGPUAS::LOCAL_ADDRESS:
525f5b36e56SScott Linder     return StringRef("local");
526f5b36e56SScott Linder   case AMDGPUAS::FLAT_ADDRESS:
527f5b36e56SScott Linder     return StringRef("generic");
528f5b36e56SScott Linder   case AMDGPUAS::REGION_ADDRESS:
529f5b36e56SScott Linder     return StringRef("region");
530f5b36e56SScott Linder   default:
531f5b36e56SScott Linder     return None;
532f5b36e56SScott Linder   }
533f5b36e56SScott Linder }
534f5b36e56SScott Linder 
535f5b36e56SScott Linder StringRef MetadataStreamerV3::getValueKind(Type *Ty, StringRef TypeQual,
536f5b36e56SScott Linder                                            StringRef BaseTypeName) const {
5376fe949c4SKazu Hirata   if (TypeQual.contains("pipe"))
538f5b36e56SScott Linder     return "pipe";
539f5b36e56SScott Linder 
540f5b36e56SScott Linder   return StringSwitch<StringRef>(BaseTypeName)
541f5b36e56SScott Linder       .Case("image1d_t", "image")
542f5b36e56SScott Linder       .Case("image1d_array_t", "image")
543f5b36e56SScott Linder       .Case("image1d_buffer_t", "image")
544f5b36e56SScott Linder       .Case("image2d_t", "image")
545f5b36e56SScott Linder       .Case("image2d_array_t", "image")
546f5b36e56SScott Linder       .Case("image2d_array_depth_t", "image")
547f5b36e56SScott Linder       .Case("image2d_array_msaa_t", "image")
548f5b36e56SScott Linder       .Case("image2d_array_msaa_depth_t", "image")
549f5b36e56SScott Linder       .Case("image2d_depth_t", "image")
550f5b36e56SScott Linder       .Case("image2d_msaa_t", "image")
551f5b36e56SScott Linder       .Case("image2d_msaa_depth_t", "image")
552f5b36e56SScott Linder       .Case("image3d_t", "image")
553f5b36e56SScott Linder       .Case("sampler_t", "sampler")
554f5b36e56SScott Linder       .Case("queue_t", "queue")
555f5b36e56SScott Linder       .Default(isa<PointerType>(Ty)
556f5b36e56SScott Linder                    ? (Ty->getPointerAddressSpace() == AMDGPUAS::LOCAL_ADDRESS
557f5b36e56SScott Linder                           ? "dynamic_shared_pointer"
558f5b36e56SScott Linder                           : "global_buffer")
559f5b36e56SScott Linder                    : "by_value");
560f5b36e56SScott Linder }
561f5b36e56SScott Linder 
562f5b36e56SScott Linder std::string MetadataStreamerV3::getTypeName(Type *Ty, bool Signed) const {
563f5b36e56SScott Linder   switch (Ty->getTypeID()) {
564f5b36e56SScott Linder   case Type::IntegerTyID: {
565f5b36e56SScott Linder     if (!Signed)
566f5b36e56SScott Linder       return (Twine('u') + getTypeName(Ty, true)).str();
567f5b36e56SScott Linder 
568f5b36e56SScott Linder     auto BitWidth = Ty->getIntegerBitWidth();
569f5b36e56SScott Linder     switch (BitWidth) {
570f5b36e56SScott Linder     case 8:
571f5b36e56SScott Linder       return "char";
572f5b36e56SScott Linder     case 16:
573f5b36e56SScott Linder       return "short";
574f5b36e56SScott Linder     case 32:
575f5b36e56SScott Linder       return "int";
576f5b36e56SScott Linder     case 64:
577f5b36e56SScott Linder       return "long";
578f5b36e56SScott Linder     default:
579f5b36e56SScott Linder       return (Twine('i') + Twine(BitWidth)).str();
580f5b36e56SScott Linder     }
581f5b36e56SScott Linder   }
582f5b36e56SScott Linder   case Type::HalfTyID:
583f5b36e56SScott Linder     return "half";
584f5b36e56SScott Linder   case Type::FloatTyID:
585f5b36e56SScott Linder     return "float";
586f5b36e56SScott Linder   case Type::DoubleTyID:
587f5b36e56SScott Linder     return "double";
5882dea3f12SChristopher Tetreault   case Type::FixedVectorTyID: {
5893254a001SChristopher Tetreault     auto VecTy = cast<FixedVectorType>(Ty);
590f5b36e56SScott Linder     auto ElTy = VecTy->getElementType();
591e634f482SChristopher Tetreault     auto NumElements = VecTy->getNumElements();
592f5b36e56SScott Linder     return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
593f5b36e56SScott Linder   }
594f5b36e56SScott Linder   default:
595f5b36e56SScott Linder     return "unknown";
596f5b36e56SScott Linder   }
597f5b36e56SScott Linder }
598f5b36e56SScott Linder 
599ed0b9af9STim Renouf msgpack::ArrayDocNode
600f5b36e56SScott Linder MetadataStreamerV3::getWorkGroupDimensions(MDNode *Node) const {
601ed0b9af9STim Renouf   auto Dims = HSAMetadataDoc->getArrayNode();
602f5b36e56SScott Linder   if (Node->getNumOperands() != 3)
603f5b36e56SScott Linder     return Dims;
604f5b36e56SScott Linder 
605f5b36e56SScott Linder   for (auto &Op : Node->operands())
606ed0b9af9STim Renouf     Dims.push_back(Dims.getDocument()->getNode(
607ed0b9af9STim Renouf         uint64_t(mdconst::extract<ConstantInt>(Op)->getZExtValue())));
608f5b36e56SScott Linder   return Dims;
609f5b36e56SScott Linder }
610f5b36e56SScott Linder 
611f5b36e56SScott Linder void MetadataStreamerV3::emitVersion() {
612ed0b9af9STim Renouf   auto Version = HSAMetadataDoc->getArrayNode();
613f4ace637SKonstantin Zhuravlyov   Version.push_back(Version.getDocument()->getNode(VersionMajorV3));
614f4ace637SKonstantin Zhuravlyov   Version.push_back(Version.getDocument()->getNode(VersionMinorV3));
615ed0b9af9STim Renouf   getRootMetadata("amdhsa.version") = Version;
616f5b36e56SScott Linder }
617f5b36e56SScott Linder 
618f5b36e56SScott Linder void MetadataStreamerV3::emitPrintf(const Module &Mod) {
619f5b36e56SScott Linder   auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
620f5b36e56SScott Linder   if (!Node)
621f5b36e56SScott Linder     return;
622f5b36e56SScott Linder 
623ed0b9af9STim Renouf   auto Printf = HSAMetadataDoc->getArrayNode();
624f5b36e56SScott Linder   for (auto Op : Node->operands())
625f5b36e56SScott Linder     if (Op->getNumOperands())
626ed0b9af9STim Renouf       Printf.push_back(Printf.getDocument()->getNode(
627ed0b9af9STim Renouf           cast<MDString>(Op->getOperand(0))->getString(), /*Copy=*/true));
628ed0b9af9STim Renouf   getRootMetadata("amdhsa.printf") = Printf;
629f5b36e56SScott Linder }
630f5b36e56SScott Linder 
631f5b36e56SScott Linder void MetadataStreamerV3::emitKernelLanguage(const Function &Func,
632ed0b9af9STim Renouf                                             msgpack::MapDocNode Kern) {
633f5b36e56SScott Linder   // TODO: What about other languages?
634f5b36e56SScott Linder   auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
635f5b36e56SScott Linder   if (!Node || !Node->getNumOperands())
636f5b36e56SScott Linder     return;
637f5b36e56SScott Linder   auto Op0 = Node->getOperand(0);
638f5b36e56SScott Linder   if (Op0->getNumOperands() <= 1)
639f5b36e56SScott Linder     return;
640f5b36e56SScott Linder 
641ed0b9af9STim Renouf   Kern[".language"] = Kern.getDocument()->getNode("OpenCL C");
642ed0b9af9STim Renouf   auto LanguageVersion = Kern.getDocument()->getArrayNode();
643ed0b9af9STim Renouf   LanguageVersion.push_back(Kern.getDocument()->getNode(
644f5b36e56SScott Linder       mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue()));
645ed0b9af9STim Renouf   LanguageVersion.push_back(Kern.getDocument()->getNode(
646f5b36e56SScott Linder       mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue()));
647ed0b9af9STim Renouf   Kern[".language_version"] = LanguageVersion;
648f5b36e56SScott Linder }
649f5b36e56SScott Linder 
650f5b36e56SScott Linder void MetadataStreamerV3::emitKernelAttrs(const Function &Func,
651ed0b9af9STim Renouf                                          msgpack::MapDocNode Kern) {
652f5b36e56SScott Linder 
653f5b36e56SScott Linder   if (auto Node = Func.getMetadata("reqd_work_group_size"))
654f5b36e56SScott Linder     Kern[".reqd_workgroup_size"] = getWorkGroupDimensions(Node);
655f5b36e56SScott Linder   if (auto Node = Func.getMetadata("work_group_size_hint"))
656f5b36e56SScott Linder     Kern[".workgroup_size_hint"] = getWorkGroupDimensions(Node);
657f5b36e56SScott Linder   if (auto Node = Func.getMetadata("vec_type_hint")) {
658ed0b9af9STim Renouf     Kern[".vec_type_hint"] = Kern.getDocument()->getNode(
659ed0b9af9STim Renouf         getTypeName(
660f5b36e56SScott Linder             cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
661ed0b9af9STim Renouf             mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue()),
662ed0b9af9STim Renouf         /*Copy=*/true);
663f5b36e56SScott Linder   }
664f5b36e56SScott Linder   if (Func.hasFnAttribute("runtime-handle")) {
665ed0b9af9STim Renouf     Kern[".device_enqueue_symbol"] = Kern.getDocument()->getNode(
666ed0b9af9STim Renouf         Func.getFnAttribute("runtime-handle").getValueAsString().str(),
667ed0b9af9STim Renouf         /*Copy=*/true);
668f5b36e56SScott Linder   }
6695173854fSReshabh Sharma   if (Func.hasFnAttribute("device-init"))
6705173854fSReshabh Sharma     Kern[".kind"] = Kern.getDocument()->getNode("init");
6715173854fSReshabh Sharma   else if (Func.hasFnAttribute("device-fini"))
6725173854fSReshabh Sharma     Kern[".kind"] = Kern.getDocument()->getNode("fini");
673f5b36e56SScott Linder }
674f5b36e56SScott Linder 
6751194b9cdSChangpeng Fang void MetadataStreamerV3::emitKernelArgs(const MachineFunction &MF,
676ed0b9af9STim Renouf                                         msgpack::MapDocNode Kern) {
6771194b9cdSChangpeng Fang   auto &Func = MF.getFunction();
678f5b36e56SScott Linder   unsigned Offset = 0;
679ed0b9af9STim Renouf   auto Args = HSAMetadataDoc->getArrayNode();
680f5b36e56SScott Linder   for (auto &Arg : Func.args())
681ed0b9af9STim Renouf     emitKernelArg(Arg, Offset, Args);
682f5b36e56SScott Linder 
6831194b9cdSChangpeng Fang   emitHiddenKernelArgs(MF, Offset, Args);
684f5b36e56SScott Linder 
685ed0b9af9STim Renouf   Kern[".args"] = Args;
686f5b36e56SScott Linder }
687f5b36e56SScott Linder 
688f5b36e56SScott Linder void MetadataStreamerV3::emitKernelArg(const Argument &Arg, unsigned &Offset,
689ed0b9af9STim Renouf                                        msgpack::ArrayDocNode Args) {
690f5b36e56SScott Linder   auto Func = Arg.getParent();
691f5b36e56SScott Linder   auto ArgNo = Arg.getArgNo();
692f5b36e56SScott Linder   const MDNode *Node;
693f5b36e56SScott Linder 
694f5b36e56SScott Linder   StringRef Name;
695f5b36e56SScott Linder   Node = Func->getMetadata("kernel_arg_name");
696f5b36e56SScott Linder   if (Node && ArgNo < Node->getNumOperands())
697f5b36e56SScott Linder     Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
698f5b36e56SScott Linder   else if (Arg.hasName())
699f5b36e56SScott Linder     Name = Arg.getName();
700f5b36e56SScott Linder 
701f5b36e56SScott Linder   StringRef TypeName;
702f5b36e56SScott Linder   Node = Func->getMetadata("kernel_arg_type");
703f5b36e56SScott Linder   if (Node && ArgNo < Node->getNumOperands())
704f5b36e56SScott Linder     TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
705f5b36e56SScott Linder 
706f5b36e56SScott Linder   StringRef BaseTypeName;
707f5b36e56SScott Linder   Node = Func->getMetadata("kernel_arg_base_type");
708f5b36e56SScott Linder   if (Node && ArgNo < Node->getNumOperands())
709f5b36e56SScott Linder     BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
710f5b36e56SScott Linder 
711f5b36e56SScott Linder   StringRef AccQual;
712f5b36e56SScott Linder   if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() &&
713f5b36e56SScott Linder       Arg.hasNoAliasAttr()) {
714f5b36e56SScott Linder     AccQual = "read_only";
715f5b36e56SScott Linder   } else {
716f5b36e56SScott Linder     Node = Func->getMetadata("kernel_arg_access_qual");
717f5b36e56SScott Linder     if (Node && ArgNo < Node->getNumOperands())
718f5b36e56SScott Linder       AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
719f5b36e56SScott Linder   }
720f5b36e56SScott Linder 
721f5b36e56SScott Linder   StringRef TypeQual;
722f5b36e56SScott Linder   Node = Func->getMetadata("kernel_arg_type_qual");
723f5b36e56SScott Linder   if (Node && ArgNo < Node->getNumOperands())
724f5b36e56SScott Linder     TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
725f5b36e56SScott Linder 
726f5b36e56SScott Linder   const DataLayout &DL = Func->getParent()->getDataLayout();
727f5b36e56SScott Linder 
728d3085c25SGuillaume Chatelet   MaybeAlign PointeeAlign;
7291168119cSMatt Arsenault   Type *Ty = Arg.hasByRefAttr() ? Arg.getParamByRefType() : Arg.getType();
7301168119cSMatt Arsenault 
7311168119cSMatt Arsenault   // FIXME: Need to distinguish in memory alignment from pointer alignment.
732f5b36e56SScott Linder   if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
733a5e324e3SNikita Popov     if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS)
734a5e324e3SNikita Popov       PointeeAlign = Arg.getParamAlign().valueOrOne();
735f5b36e56SScott Linder   }
736f5b36e56SScott Linder 
7371168119cSMatt Arsenault   // There's no distinction between byval aggregates and raw aggregates.
7381168119cSMatt Arsenault   Type *ArgTy;
7391168119cSMatt Arsenault   Align ArgAlign;
7401168119cSMatt Arsenault   std::tie(ArgTy, ArgAlign) = getArgumentTypeAlign(Arg, DL);
7411168119cSMatt Arsenault 
7421168119cSMatt Arsenault   emitKernelArg(DL, ArgTy, ArgAlign,
7431168119cSMatt Arsenault                 getValueKind(ArgTy, TypeQual, BaseTypeName), Offset, Args,
7441168119cSMatt Arsenault                 PointeeAlign, Name, TypeName, BaseTypeName, AccQual, TypeQual);
745f5b36e56SScott Linder }
746f5b36e56SScott Linder 
7471168119cSMatt Arsenault void MetadataStreamerV3::emitKernelArg(
7481168119cSMatt Arsenault     const DataLayout &DL, Type *Ty, Align Alignment, StringRef ValueKind,
7491168119cSMatt Arsenault     unsigned &Offset, msgpack::ArrayDocNode Args, MaybeAlign PointeeAlign,
7501168119cSMatt Arsenault     StringRef Name, StringRef TypeName, StringRef BaseTypeName,
751f5b36e56SScott Linder     StringRef AccQual, StringRef TypeQual) {
752ed0b9af9STim Renouf   auto Arg = Args.getDocument()->getMapNode();
753f5b36e56SScott Linder 
754f5b36e56SScott Linder   if (!Name.empty())
755ed0b9af9STim Renouf     Arg[".name"] = Arg.getDocument()->getNode(Name, /*Copy=*/true);
756f5b36e56SScott Linder   if (!TypeName.empty())
757ed0b9af9STim Renouf     Arg[".type_name"] = Arg.getDocument()->getNode(TypeName, /*Copy=*/true);
758f5b36e56SScott Linder   auto Size = DL.getTypeAllocSize(Ty);
759ed0b9af9STim Renouf   Arg[".size"] = Arg.getDocument()->getNode(Size);
760d3085c25SGuillaume Chatelet   Offset = alignTo(Offset, Alignment);
761ed0b9af9STim Renouf   Arg[".offset"] = Arg.getDocument()->getNode(Offset);
762f5b36e56SScott Linder   Offset += Size;
763ed0b9af9STim Renouf   Arg[".value_kind"] = Arg.getDocument()->getNode(ValueKind, /*Copy=*/true);
764f5b36e56SScott Linder   if (PointeeAlign)
765d3085c25SGuillaume Chatelet     Arg[".pointee_align"] = Arg.getDocument()->getNode(PointeeAlign->value());
766f5b36e56SScott Linder 
767f5b36e56SScott Linder   if (auto PtrTy = dyn_cast<PointerType>(Ty))
768f5b36e56SScott Linder     if (auto Qualifier = getAddressSpaceQualifier(PtrTy->getAddressSpace()))
769ed0b9af9STim Renouf       Arg[".address_space"] = Arg.getDocument()->getNode(*Qualifier, /*Copy=*/true);
770f5b36e56SScott Linder 
771f5b36e56SScott Linder   if (auto AQ = getAccessQualifier(AccQual))
772ed0b9af9STim Renouf     Arg[".access"] = Arg.getDocument()->getNode(*AQ, /*Copy=*/true);
773f5b36e56SScott Linder 
774f5b36e56SScott Linder   // TODO: Emit Arg[".actual_access"].
775f5b36e56SScott Linder 
776f5b36e56SScott Linder   SmallVector<StringRef, 1> SplitTypeQuals;
777f5b36e56SScott Linder   TypeQual.split(SplitTypeQuals, " ", -1, false);
778f5b36e56SScott Linder   for (StringRef Key : SplitTypeQuals) {
779f5b36e56SScott Linder     if (Key == "const")
780ed0b9af9STim Renouf       Arg[".is_const"] = Arg.getDocument()->getNode(true);
781f5b36e56SScott Linder     else if (Key == "restrict")
782ed0b9af9STim Renouf       Arg[".is_restrict"] = Arg.getDocument()->getNode(true);
783f5b36e56SScott Linder     else if (Key == "volatile")
784ed0b9af9STim Renouf       Arg[".is_volatile"] = Arg.getDocument()->getNode(true);
785f5b36e56SScott Linder     else if (Key == "pipe")
786ed0b9af9STim Renouf       Arg[".is_pipe"] = Arg.getDocument()->getNode(true);
787f5b36e56SScott Linder   }
788f5b36e56SScott Linder 
789ed0b9af9STim Renouf   Args.push_back(Arg);
790f5b36e56SScott Linder }
791f5b36e56SScott Linder 
7921194b9cdSChangpeng Fang void MetadataStreamerV3::emitHiddenKernelArgs(const MachineFunction &MF,
793f5b36e56SScott Linder                                               unsigned &Offset,
794ed0b9af9STim Renouf                                               msgpack::ArrayDocNode Args) {
7951194b9cdSChangpeng Fang   auto &Func = MF.getFunction();
7961194b9cdSChangpeng Fang   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
797d8f99bb6SSameer Sahasrabuddhe   const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
7981194b9cdSChangpeng Fang 
799ae0ba7deSMatt Arsenault   unsigned HiddenArgNumBytes = ST.getImplicitArgNumBytes(Func);
800f5b36e56SScott Linder   if (!HiddenArgNumBytes)
801f5b36e56SScott Linder     return;
802f5b36e56SScott Linder 
803095c48fdSkpyzhov   const Module *M = Func.getParent();
804095c48fdSkpyzhov   auto &DL = M->getDataLayout();
805f5b36e56SScott Linder   auto Int64Ty = Type::getInt64Ty(Func.getContext());
806f5b36e56SScott Linder 
807f5b36e56SScott Linder   if (HiddenArgNumBytes >= 8)
8081168119cSMatt Arsenault     emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset,
8091168119cSMatt Arsenault                   Args);
810f5b36e56SScott Linder   if (HiddenArgNumBytes >= 16)
8111168119cSMatt Arsenault     emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset,
8121168119cSMatt Arsenault                   Args);
813f5b36e56SScott Linder   if (HiddenArgNumBytes >= 24)
8141168119cSMatt Arsenault     emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset,
8151168119cSMatt Arsenault                   Args);
816f5b36e56SScott Linder 
817f5b36e56SScott Linder   auto Int8PtrTy =
818f5b36e56SScott Linder       Type::getInt8PtrTy(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
819f5b36e56SScott Linder 
820095c48fdSkpyzhov   // Emit "printf buffer" argument if printf is used, emit "hostcall buffer"
821095c48fdSkpyzhov   // if "hostcall" module flag is set, otherwise emit dummy "none" argument.
822f5b36e56SScott Linder   if (HiddenArgNumBytes >= 32) {
823095c48fdSkpyzhov     if (M->getNamedMetadata("llvm.printf.fmts"))
8241168119cSMatt Arsenault       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset,
8251168119cSMatt Arsenault                     Args);
826d8f99bb6SSameer Sahasrabuddhe     else if (MFI.hasHostcallPtr()) {
82752c5014dSSameer Sahasrabuddhe       // The printf runtime binding pass should have ensured that hostcall and
82852c5014dSSameer Sahasrabuddhe       // printf are not used in the same module.
829095c48fdSkpyzhov       assert(!M->getNamedMetadata("llvm.printf.fmts"));
8301168119cSMatt Arsenault       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset,
8311168119cSMatt Arsenault                     Args);
83252c5014dSSameer Sahasrabuddhe     } else
8331168119cSMatt Arsenault       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
834f5b36e56SScott Linder   }
835f5b36e56SScott Linder 
836f5b36e56SScott Linder   // Emit "default queue" and "completion action" arguments if enqueue kernel is
837f5b36e56SScott Linder   // used, otherwise emit dummy "none" arguments.
838f5b36e56SScott Linder   if (HiddenArgNumBytes >= 48) {
839f5b36e56SScott Linder     if (Func.hasFnAttribute("calls-enqueue-kernel")) {
8401168119cSMatt Arsenault       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset,
8411168119cSMatt Arsenault                     Args);
8421168119cSMatt Arsenault       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset,
8431168119cSMatt Arsenault                     Args);
844f5b36e56SScott Linder     } else {
8451168119cSMatt Arsenault       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
8461168119cSMatt Arsenault       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
847f5b36e56SScott Linder     }
848f5b36e56SScott Linder   }
849a6241352SYaxun Liu 
850a6241352SYaxun Liu   // Emit the pointer argument for multi-grid object.
851a6241352SYaxun Liu   if (HiddenArgNumBytes >= 56)
8521168119cSMatt Arsenault     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset,
8531168119cSMatt Arsenault                   Args);
854f5b36e56SScott Linder }
855f5b36e56SScott Linder 
856ed0b9af9STim Renouf msgpack::MapDocNode
857f5b36e56SScott Linder MetadataStreamerV3::getHSAKernelProps(const MachineFunction &MF,
858f5b36e56SScott Linder                                       const SIProgramInfo &ProgramInfo) const {
859f5b36e56SScott Linder   const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
860f5b36e56SScott Linder   const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
861f5b36e56SScott Linder   const Function &F = MF.getFunction();
862f5b36e56SScott Linder 
863ed0b9af9STim Renouf   auto Kern = HSAMetadataDoc->getMapNode();
864f5b36e56SScott Linder 
865b65fa483SGuillaume Chatelet   Align MaxKernArgAlign;
866ed0b9af9STim Renouf   Kern[".kernarg_segment_size"] = Kern.getDocument()->getNode(
867f5b36e56SScott Linder       STM.getKernArgSegmentSize(F, MaxKernArgAlign));
868f5b36e56SScott Linder   Kern[".group_segment_fixed_size"] =
869ed0b9af9STim Renouf       Kern.getDocument()->getNode(ProgramInfo.LDSSize);
870f5b36e56SScott Linder   Kern[".private_segment_fixed_size"] =
871ed0b9af9STim Renouf       Kern.getDocument()->getNode(ProgramInfo.ScratchSize);
87290ff1487SMatt Arsenault 
87390ff1487SMatt Arsenault   // FIXME: The metadata treats the minimum as 16?
874f5b36e56SScott Linder   Kern[".kernarg_segment_align"] =
875b65fa483SGuillaume Chatelet       Kern.getDocument()->getNode(std::max(Align(4), MaxKernArgAlign).value());
876f5b36e56SScott Linder   Kern[".wavefront_size"] =
877ed0b9af9STim Renouf       Kern.getDocument()->getNode(STM.getWavefrontSize());
878ed0b9af9STim Renouf   Kern[".sgpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumSGPR);
879ed0b9af9STim Renouf   Kern[".vgpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumVGPR);
88074702444SJacob Lambert 
88174702444SJacob Lambert   // Only add AGPR count to metadata for supported devices
88274702444SJacob Lambert   if (STM.hasMAIInsts()) {
88374702444SJacob Lambert     Kern[".agpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumAccVGPR);
88474702444SJacob Lambert   }
88574702444SJacob Lambert 
886f5b36e56SScott Linder   Kern[".max_flat_workgroup_size"] =
887ed0b9af9STim Renouf       Kern.getDocument()->getNode(MFI.getMaxFlatWorkGroupSize());
888f5b36e56SScott Linder   Kern[".sgpr_spill_count"] =
889ed0b9af9STim Renouf       Kern.getDocument()->getNode(MFI.getNumSpilledSGPRs());
890f5b36e56SScott Linder   Kern[".vgpr_spill_count"] =
891ed0b9af9STim Renouf       Kern.getDocument()->getNode(MFI.getNumSpilledVGPRs());
892f5b36e56SScott Linder 
893ed0b9af9STim Renouf   return Kern;
894f5b36e56SScott Linder }
895f5b36e56SScott Linder 
896f5b36e56SScott Linder bool MetadataStreamerV3::emitTo(AMDGPUTargetStreamer &TargetStreamer) {
897ed0b9af9STim Renouf   return TargetStreamer.EmitHSAMetadata(*HSAMetadataDoc, true);
898f5b36e56SScott Linder }
899f5b36e56SScott Linder 
900f4ace637SKonstantin Zhuravlyov void MetadataStreamerV3::begin(const Module &Mod,
901f4ace637SKonstantin Zhuravlyov                                const IsaInfo::AMDGPUTargetID &TargetID) {
902f5b36e56SScott Linder   emitVersion();
903f5b36e56SScott Linder   emitPrintf(Mod);
904ed0b9af9STim Renouf   getRootMetadata("amdhsa.kernels") = HSAMetadataDoc->getArrayNode();
905f5b36e56SScott Linder }
906f5b36e56SScott Linder 
907f5b36e56SScott Linder void MetadataStreamerV3::end() {
908f5b36e56SScott Linder   std::string HSAMetadataString;
909f5b36e56SScott Linder   raw_string_ostream StrOS(HSAMetadataString);
910ed0b9af9STim Renouf   HSAMetadataDoc->toYAML(StrOS);
911f5b36e56SScott Linder 
912f5b36e56SScott Linder   if (DumpHSAMetadata)
913f5b36e56SScott Linder     dump(StrOS.str());
914f5b36e56SScott Linder   if (VerifyHSAMetadata)
915f5b36e56SScott Linder     verify(StrOS.str());
916f5b36e56SScott Linder }
917f5b36e56SScott Linder 
918f5b36e56SScott Linder void MetadataStreamerV3::emitKernel(const MachineFunction &MF,
919f5b36e56SScott Linder                                     const SIProgramInfo &ProgramInfo) {
920f5b36e56SScott Linder   auto &Func = MF.getFunction();
921ed0b9af9STim Renouf   auto Kern = getHSAKernelProps(MF, ProgramInfo);
922f5b36e56SScott Linder 
923f5b36e56SScott Linder   assert(Func.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
924f5b36e56SScott Linder          Func.getCallingConv() == CallingConv::SPIR_KERNEL);
925f5b36e56SScott Linder 
926ed0b9af9STim Renouf   auto Kernels =
927ed0b9af9STim Renouf       getRootMetadata("amdhsa.kernels").getArray(/*Convert=*/true);
928f5b36e56SScott Linder 
929f5b36e56SScott Linder   {
930ed0b9af9STim Renouf     Kern[".name"] = Kern.getDocument()->getNode(Func.getName());
931ed0b9af9STim Renouf     Kern[".symbol"] = Kern.getDocument()->getNode(
932ed0b9af9STim Renouf         (Twine(Func.getName()) + Twine(".kd")).str(), /*Copy=*/true);
933f5b36e56SScott Linder     emitKernelLanguage(Func, Kern);
934f5b36e56SScott Linder     emitKernelAttrs(Func, Kern);
9351194b9cdSChangpeng Fang     emitKernelArgs(MF, Kern);
936f5b36e56SScott Linder   }
937f5b36e56SScott Linder 
938ed0b9af9STim Renouf   Kernels.push_back(Kern);
939f5b36e56SScott Linder }
940f5b36e56SScott Linder 
941f4ace637SKonstantin Zhuravlyov //===----------------------------------------------------------------------===//
942f4ace637SKonstantin Zhuravlyov // HSAMetadataStreamerV4
943f4ace637SKonstantin Zhuravlyov //===----------------------------------------------------------------------===//
944f4ace637SKonstantin Zhuravlyov 
945f4ace637SKonstantin Zhuravlyov void MetadataStreamerV4::emitVersion() {
946f4ace637SKonstantin Zhuravlyov   auto Version = HSAMetadataDoc->getArrayNode();
947f4ace637SKonstantin Zhuravlyov   Version.push_back(Version.getDocument()->getNode(VersionMajorV4));
948f4ace637SKonstantin Zhuravlyov   Version.push_back(Version.getDocument()->getNode(VersionMinorV4));
949f4ace637SKonstantin Zhuravlyov   getRootMetadata("amdhsa.version") = Version;
950f4ace637SKonstantin Zhuravlyov }
951f4ace637SKonstantin Zhuravlyov 
952f4ace637SKonstantin Zhuravlyov void MetadataStreamerV4::emitTargetID(const IsaInfo::AMDGPUTargetID &TargetID) {
953f4ace637SKonstantin Zhuravlyov   getRootMetadata("amdhsa.target") =
954f4ace637SKonstantin Zhuravlyov       HSAMetadataDoc->getNode(TargetID.toString(), /*Copy=*/true);
955f4ace637SKonstantin Zhuravlyov }
956f4ace637SKonstantin Zhuravlyov 
957f4ace637SKonstantin Zhuravlyov void MetadataStreamerV4::begin(const Module &Mod,
958f4ace637SKonstantin Zhuravlyov                                const IsaInfo::AMDGPUTargetID &TargetID) {
959f4ace637SKonstantin Zhuravlyov   emitVersion();
960f4ace637SKonstantin Zhuravlyov   emitTargetID(TargetID);
961f4ace637SKonstantin Zhuravlyov   emitPrintf(Mod);
962f4ace637SKonstantin Zhuravlyov   getRootMetadata("amdhsa.kernels") = HSAMetadataDoc->getArrayNode();
963f4ace637SKonstantin Zhuravlyov }
964f4ace637SKonstantin Zhuravlyov 
9651194b9cdSChangpeng Fang //===----------------------------------------------------------------------===//
9661194b9cdSChangpeng Fang // HSAMetadataStreamerV5
9671194b9cdSChangpeng Fang //===----------------------------------------------------------------------===//
9681194b9cdSChangpeng Fang 
9691194b9cdSChangpeng Fang void MetadataStreamerV5::emitVersion() {
9701194b9cdSChangpeng Fang   auto Version = HSAMetadataDoc->getArrayNode();
9711194b9cdSChangpeng Fang   Version.push_back(Version.getDocument()->getNode(VersionMajorV5));
9721194b9cdSChangpeng Fang   Version.push_back(Version.getDocument()->getNode(VersionMinorV5));
9731194b9cdSChangpeng Fang   getRootMetadata("amdhsa.version") = Version;
9741194b9cdSChangpeng Fang }
9751194b9cdSChangpeng Fang 
9761194b9cdSChangpeng Fang void MetadataStreamerV5::emitHiddenKernelArgs(const MachineFunction &MF,
9771194b9cdSChangpeng Fang                                               unsigned &Offset,
9781194b9cdSChangpeng Fang                                               msgpack::ArrayDocNode Args) {
9791194b9cdSChangpeng Fang   auto &Func = MF.getFunction();
9801194b9cdSChangpeng Fang   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
9811194b9cdSChangpeng Fang   const Module *M = Func.getParent();
9821194b9cdSChangpeng Fang   auto &DL = M->getDataLayout();
983d8f99bb6SSameer Sahasrabuddhe   const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
9841194b9cdSChangpeng Fang 
9851194b9cdSChangpeng Fang   auto Int64Ty = Type::getInt64Ty(Func.getContext());
9861194b9cdSChangpeng Fang   auto Int32Ty = Type::getInt32Ty(Func.getContext());
9871194b9cdSChangpeng Fang   auto Int16Ty = Type::getInt16Ty(Func.getContext());
9881194b9cdSChangpeng Fang 
9891194b9cdSChangpeng Fang   emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_x", Offset, Args);
9901194b9cdSChangpeng Fang   emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_y", Offset, Args);
9911194b9cdSChangpeng Fang   emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_z", Offset, Args);
9921194b9cdSChangpeng Fang 
9931194b9cdSChangpeng Fang   emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_x", Offset, Args);
9941194b9cdSChangpeng Fang   emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_y", Offset, Args);
9951194b9cdSChangpeng Fang   emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_z", Offset, Args);
9961194b9cdSChangpeng Fang 
9971194b9cdSChangpeng Fang   emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_x", Offset, Args);
9981194b9cdSChangpeng Fang   emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_y", Offset, Args);
9991194b9cdSChangpeng Fang   emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_z", Offset, Args);
10001194b9cdSChangpeng Fang 
10011194b9cdSChangpeng Fang   // Reserved for hidden_tool_correlation_id.
10021194b9cdSChangpeng Fang   Offset += 8;
10031194b9cdSChangpeng Fang 
10041194b9cdSChangpeng Fang   Offset += 8; // Reserved.
10051194b9cdSChangpeng Fang 
10061194b9cdSChangpeng Fang   emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset, Args);
10071194b9cdSChangpeng Fang   emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset, Args);
10081194b9cdSChangpeng Fang   emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset, Args);
10091194b9cdSChangpeng Fang 
10101194b9cdSChangpeng Fang   emitKernelArg(DL, Int16Ty, Align(2), "hidden_grid_dims", Offset, Args);
10111194b9cdSChangpeng Fang 
10121194b9cdSChangpeng Fang   Offset += 6; // Reserved.
10131194b9cdSChangpeng Fang   auto Int8PtrTy =
10141194b9cdSChangpeng Fang       Type::getInt8PtrTy(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
10151194b9cdSChangpeng Fang 
10161194b9cdSChangpeng Fang   if (M->getNamedMetadata("llvm.printf.fmts")) {
10171194b9cdSChangpeng Fang     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset,
10181194b9cdSChangpeng Fang                   Args);
10191194b9cdSChangpeng Fang   } else
10201194b9cdSChangpeng Fang     Offset += 8; // Skipped.
10211194b9cdSChangpeng Fang 
1022d8f99bb6SSameer Sahasrabuddhe   if (MFI.hasHostcallPtr()) {
10231194b9cdSChangpeng Fang     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset,
10241194b9cdSChangpeng Fang                   Args);
10251194b9cdSChangpeng Fang   } else
10261194b9cdSChangpeng Fang     Offset += 8; // Skipped.
10271194b9cdSChangpeng Fang 
10281194b9cdSChangpeng Fang   emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset,
10291194b9cdSChangpeng Fang                 Args);
10301194b9cdSChangpeng Fang 
1031*ca62b1dbSChangpeng Fang   if (MFI.hasHeapPtr())
1032*ca62b1dbSChangpeng Fang     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_heap_v1", Offset, Args);
1033*ca62b1dbSChangpeng Fang   else
1034*ca62b1dbSChangpeng Fang     Offset += 8; // Skipped.
10351194b9cdSChangpeng Fang 
10361194b9cdSChangpeng Fang   if (Func.hasFnAttribute("calls-enqueue-kernel")) {
10371194b9cdSChangpeng Fang     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset,
10381194b9cdSChangpeng Fang                   Args);
10391194b9cdSChangpeng Fang     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset,
10401194b9cdSChangpeng Fang                   Args);
10411194b9cdSChangpeng Fang   } else
10421194b9cdSChangpeng Fang     Offset += 16; // Skipped.
10431194b9cdSChangpeng Fang 
10441194b9cdSChangpeng Fang   Offset += 72; // Reserved.
10451194b9cdSChangpeng Fang 
10461194b9cdSChangpeng Fang   // hidden_private_base and hidden_shared_base are only used by GFX8.
10471194b9cdSChangpeng Fang   if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) {
10481194b9cdSChangpeng Fang     emitKernelArg(DL, Int32Ty, Align(4), "hidden_private_base", Offset, Args);
10491194b9cdSChangpeng Fang     emitKernelArg(DL, Int32Ty, Align(4), "hidden_shared_base", Offset, Args);
10501194b9cdSChangpeng Fang   } else
10511194b9cdSChangpeng Fang     Offset += 8; // Skipped.
10521194b9cdSChangpeng Fang 
10531194b9cdSChangpeng Fang   if (MFI.hasQueuePtr())
10541194b9cdSChangpeng Fang     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_queue_ptr", Offset, Args);
10551194b9cdSChangpeng Fang }
10561194b9cdSChangpeng Fang 
105701ce144dSScott Linder } // end namespace HSAMD
105801ce144dSScott Linder } // end namespace AMDGPU
105901ce144dSScott Linder } // end namespace llvm
1060