14ba319b5SDimitry Andric //===--- AMDGPUHSAMetadataStreamer.cpp --------------------------*- C++ -*-===//
24ba319b5SDimitry Andric //
34ba319b5SDimitry Andric // The LLVM Compiler Infrastructure
44ba319b5SDimitry Andric //
54ba319b5SDimitry Andric // This file is distributed under the University of Illinois Open Source
64ba319b5SDimitry Andric // License. See LICENSE.TXT for details.
74ba319b5SDimitry Andric //
84ba319b5SDimitry Andric //===----------------------------------------------------------------------===//
94ba319b5SDimitry Andric //
104ba319b5SDimitry Andric /// \file
114ba319b5SDimitry Andric /// AMDGPU HSA Metadata Streamer.
124ba319b5SDimitry Andric ///
134ba319b5SDimitry Andric //
144ba319b5SDimitry Andric //===----------------------------------------------------------------------===//
154ba319b5SDimitry Andric
164ba319b5SDimitry Andric #include "AMDGPUHSAMetadataStreamer.h"
174ba319b5SDimitry Andric #include "AMDGPU.h"
184ba319b5SDimitry Andric #include "AMDGPUSubtarget.h"
19*b5893f02SDimitry Andric #include "MCTargetDesc/AMDGPUTargetStreamer.h"
204ba319b5SDimitry Andric #include "SIMachineFunctionInfo.h"
214ba319b5SDimitry Andric #include "SIProgramInfo.h"
224ba319b5SDimitry Andric #include "Utils/AMDGPUBaseInfo.h"
234ba319b5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
244ba319b5SDimitry Andric #include "llvm/IR/Constants.h"
254ba319b5SDimitry Andric #include "llvm/IR/Module.h"
264ba319b5SDimitry Andric #include "llvm/Support/raw_ostream.h"
274ba319b5SDimitry Andric
284ba319b5SDimitry Andric namespace llvm {
294ba319b5SDimitry Andric
304ba319b5SDimitry Andric static cl::opt<bool> DumpHSAMetadata(
314ba319b5SDimitry Andric "amdgpu-dump-hsa-metadata",
324ba319b5SDimitry Andric cl::desc("Dump AMDGPU HSA Metadata"));
334ba319b5SDimitry Andric static cl::opt<bool> VerifyHSAMetadata(
344ba319b5SDimitry Andric "amdgpu-verify-hsa-metadata",
354ba319b5SDimitry Andric cl::desc("Verify AMDGPU HSA Metadata"));
364ba319b5SDimitry Andric
374ba319b5SDimitry Andric namespace AMDGPU {
384ba319b5SDimitry Andric namespace HSAMD {
394ba319b5SDimitry Andric
40*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
41*b5893f02SDimitry Andric // HSAMetadataStreamerV2
42*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
dump(StringRef HSAMetadataString) const43*b5893f02SDimitry Andric void MetadataStreamerV2::dump(StringRef HSAMetadataString) const {
444ba319b5SDimitry Andric errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
454ba319b5SDimitry Andric }
464ba319b5SDimitry Andric
verify(StringRef HSAMetadataString) const47*b5893f02SDimitry Andric void MetadataStreamerV2::verify(StringRef HSAMetadataString) const {
484ba319b5SDimitry Andric errs() << "AMDGPU HSA Metadata Parser Test: ";
494ba319b5SDimitry Andric
504ba319b5SDimitry Andric HSAMD::Metadata FromHSAMetadataString;
514ba319b5SDimitry Andric if (fromString(HSAMetadataString, FromHSAMetadataString)) {
524ba319b5SDimitry Andric errs() << "FAIL\n";
534ba319b5SDimitry Andric return;
544ba319b5SDimitry Andric }
554ba319b5SDimitry Andric
564ba319b5SDimitry Andric std::string ToHSAMetadataString;
574ba319b5SDimitry Andric if (toString(FromHSAMetadataString, ToHSAMetadataString)) {
584ba319b5SDimitry Andric errs() << "FAIL\n";
594ba319b5SDimitry Andric return;
604ba319b5SDimitry Andric }
614ba319b5SDimitry Andric
624ba319b5SDimitry Andric errs() << (HSAMetadataString == ToHSAMetadataString ? "PASS" : "FAIL")
634ba319b5SDimitry Andric << '\n';
644ba319b5SDimitry Andric if (HSAMetadataString != ToHSAMetadataString) {
654ba319b5SDimitry Andric errs() << "Original input: " << HSAMetadataString << '\n'
664ba319b5SDimitry Andric << "Produced output: " << ToHSAMetadataString << '\n';
674ba319b5SDimitry Andric }
684ba319b5SDimitry Andric }
694ba319b5SDimitry Andric
70*b5893f02SDimitry Andric AccessQualifier
getAccessQualifier(StringRef AccQual) const71*b5893f02SDimitry Andric MetadataStreamerV2::getAccessQualifier(StringRef AccQual) const {
724ba319b5SDimitry Andric if (AccQual.empty())
734ba319b5SDimitry Andric return AccessQualifier::Unknown;
744ba319b5SDimitry Andric
754ba319b5SDimitry Andric return StringSwitch<AccessQualifier>(AccQual)
764ba319b5SDimitry Andric .Case("read_only", AccessQualifier::ReadOnly)
774ba319b5SDimitry Andric .Case("write_only", AccessQualifier::WriteOnly)
784ba319b5SDimitry Andric .Case("read_write", AccessQualifier::ReadWrite)
794ba319b5SDimitry Andric .Default(AccessQualifier::Default);
804ba319b5SDimitry Andric }
814ba319b5SDimitry Andric
82*b5893f02SDimitry Andric AddressSpaceQualifier
getAddressSpaceQualifier(unsigned AddressSpace) const83*b5893f02SDimitry Andric MetadataStreamerV2::getAddressSpaceQualifier(
844ba319b5SDimitry Andric unsigned AddressSpace) const {
85*b5893f02SDimitry Andric switch (AddressSpace) {
86*b5893f02SDimitry Andric case AMDGPUAS::PRIVATE_ADDRESS:
874ba319b5SDimitry Andric return AddressSpaceQualifier::Private;
88*b5893f02SDimitry Andric case AMDGPUAS::GLOBAL_ADDRESS:
894ba319b5SDimitry Andric return AddressSpaceQualifier::Global;
90*b5893f02SDimitry Andric case AMDGPUAS::CONSTANT_ADDRESS:
914ba319b5SDimitry Andric return AddressSpaceQualifier::Constant;
92*b5893f02SDimitry Andric case AMDGPUAS::LOCAL_ADDRESS:
934ba319b5SDimitry Andric return AddressSpaceQualifier::Local;
94*b5893f02SDimitry Andric case AMDGPUAS::FLAT_ADDRESS:
954ba319b5SDimitry Andric return AddressSpaceQualifier::Generic;
96*b5893f02SDimitry Andric case AMDGPUAS::REGION_ADDRESS:
974ba319b5SDimitry Andric return AddressSpaceQualifier::Region;
98*b5893f02SDimitry Andric default:
99*b5893f02SDimitry Andric return AddressSpaceQualifier::Unknown;
100*b5893f02SDimitry Andric }
1014ba319b5SDimitry Andric }
1024ba319b5SDimitry Andric
getValueKind(Type * Ty,StringRef TypeQual,StringRef BaseTypeName) const103*b5893f02SDimitry Andric ValueKind MetadataStreamerV2::getValueKind(Type *Ty, StringRef TypeQual,
1044ba319b5SDimitry Andric StringRef BaseTypeName) const {
1054ba319b5SDimitry Andric if (TypeQual.find("pipe") != StringRef::npos)
1064ba319b5SDimitry Andric return ValueKind::Pipe;
1074ba319b5SDimitry Andric
1084ba319b5SDimitry Andric return StringSwitch<ValueKind>(BaseTypeName)
1094ba319b5SDimitry Andric .Case("image1d_t", ValueKind::Image)
1104ba319b5SDimitry Andric .Case("image1d_array_t", ValueKind::Image)
1114ba319b5SDimitry Andric .Case("image1d_buffer_t", ValueKind::Image)
1124ba319b5SDimitry Andric .Case("image2d_t", ValueKind::Image)
1134ba319b5SDimitry Andric .Case("image2d_array_t", ValueKind::Image)
1144ba319b5SDimitry Andric .Case("image2d_array_depth_t", ValueKind::Image)
1154ba319b5SDimitry Andric .Case("image2d_array_msaa_t", ValueKind::Image)
1164ba319b5SDimitry Andric .Case("image2d_array_msaa_depth_t", ValueKind::Image)
1174ba319b5SDimitry Andric .Case("image2d_depth_t", ValueKind::Image)
1184ba319b5SDimitry Andric .Case("image2d_msaa_t", ValueKind::Image)
1194ba319b5SDimitry Andric .Case("image2d_msaa_depth_t", ValueKind::Image)
1204ba319b5SDimitry Andric .Case("image3d_t", ValueKind::Image)
1214ba319b5SDimitry Andric .Case("sampler_t", ValueKind::Sampler)
1224ba319b5SDimitry Andric .Case("queue_t", ValueKind::Queue)
1234ba319b5SDimitry Andric .Default(isa<PointerType>(Ty) ?
1244ba319b5SDimitry Andric (Ty->getPointerAddressSpace() ==
125*b5893f02SDimitry Andric AMDGPUAS::LOCAL_ADDRESS ?
1264ba319b5SDimitry Andric ValueKind::DynamicSharedPointer :
1274ba319b5SDimitry Andric ValueKind::GlobalBuffer) :
1284ba319b5SDimitry Andric ValueKind::ByValue);
1294ba319b5SDimitry Andric }
1304ba319b5SDimitry Andric
getValueType(Type * Ty,StringRef TypeName) const131*b5893f02SDimitry Andric ValueType MetadataStreamerV2::getValueType(Type *Ty, StringRef TypeName) const {
1324ba319b5SDimitry Andric switch (Ty->getTypeID()) {
1334ba319b5SDimitry Andric case Type::IntegerTyID: {
1344ba319b5SDimitry Andric auto Signed = !TypeName.startswith("u");
1354ba319b5SDimitry Andric switch (Ty->getIntegerBitWidth()) {
1364ba319b5SDimitry Andric case 8:
1374ba319b5SDimitry Andric return Signed ? ValueType::I8 : ValueType::U8;
1384ba319b5SDimitry Andric case 16:
1394ba319b5SDimitry Andric return Signed ? ValueType::I16 : ValueType::U16;
1404ba319b5SDimitry Andric case 32:
1414ba319b5SDimitry Andric return Signed ? ValueType::I32 : ValueType::U32;
1424ba319b5SDimitry Andric case 64:
1434ba319b5SDimitry Andric return Signed ? ValueType::I64 : ValueType::U64;
1444ba319b5SDimitry Andric default:
1454ba319b5SDimitry Andric return ValueType::Struct;
1464ba319b5SDimitry Andric }
1474ba319b5SDimitry Andric }
1484ba319b5SDimitry Andric case Type::HalfTyID:
1494ba319b5SDimitry Andric return ValueType::F16;
1504ba319b5SDimitry Andric case Type::FloatTyID:
1514ba319b5SDimitry Andric return ValueType::F32;
1524ba319b5SDimitry Andric case Type::DoubleTyID:
1534ba319b5SDimitry Andric return ValueType::F64;
1544ba319b5SDimitry Andric case Type::PointerTyID:
1554ba319b5SDimitry Andric return getValueType(Ty->getPointerElementType(), TypeName);
1564ba319b5SDimitry Andric case Type::VectorTyID:
1574ba319b5SDimitry Andric return getValueType(Ty->getVectorElementType(), TypeName);
1584ba319b5SDimitry Andric default:
1594ba319b5SDimitry Andric return ValueType::Struct;
1604ba319b5SDimitry Andric }
1614ba319b5SDimitry Andric }
1624ba319b5SDimitry Andric
getTypeName(Type * Ty,bool Signed) const163*b5893f02SDimitry Andric std::string MetadataStreamerV2::getTypeName(Type *Ty, bool Signed) const {
1644ba319b5SDimitry Andric switch (Ty->getTypeID()) {
1654ba319b5SDimitry Andric case Type::IntegerTyID: {
1664ba319b5SDimitry Andric if (!Signed)
1674ba319b5SDimitry Andric return (Twine('u') + getTypeName(Ty, true)).str();
1684ba319b5SDimitry Andric
1694ba319b5SDimitry Andric auto BitWidth = Ty->getIntegerBitWidth();
1704ba319b5SDimitry Andric switch (BitWidth) {
1714ba319b5SDimitry Andric case 8:
1724ba319b5SDimitry Andric return "char";
1734ba319b5SDimitry Andric case 16:
1744ba319b5SDimitry Andric return "short";
1754ba319b5SDimitry Andric case 32:
1764ba319b5SDimitry Andric return "int";
1774ba319b5SDimitry Andric case 64:
1784ba319b5SDimitry Andric return "long";
1794ba319b5SDimitry Andric default:
1804ba319b5SDimitry Andric return (Twine('i') + Twine(BitWidth)).str();
1814ba319b5SDimitry Andric }
1824ba319b5SDimitry Andric }
1834ba319b5SDimitry Andric case Type::HalfTyID:
1844ba319b5SDimitry Andric return "half";
1854ba319b5SDimitry Andric case Type::FloatTyID:
1864ba319b5SDimitry Andric return "float";
1874ba319b5SDimitry Andric case Type::DoubleTyID:
1884ba319b5SDimitry Andric return "double";
1894ba319b5SDimitry Andric case Type::VectorTyID: {
1904ba319b5SDimitry Andric auto VecTy = cast<VectorType>(Ty);
1914ba319b5SDimitry Andric auto ElTy = VecTy->getElementType();
1924ba319b5SDimitry Andric auto NumElements = VecTy->getVectorNumElements();
1934ba319b5SDimitry Andric return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
1944ba319b5SDimitry Andric }
1954ba319b5SDimitry Andric default:
1964ba319b5SDimitry Andric return "unknown";
1974ba319b5SDimitry Andric }
1984ba319b5SDimitry Andric }
1994ba319b5SDimitry Andric
200*b5893f02SDimitry Andric std::vector<uint32_t>
getWorkGroupDimensions(MDNode * Node) const201*b5893f02SDimitry Andric MetadataStreamerV2::getWorkGroupDimensions(MDNode *Node) const {
2024ba319b5SDimitry Andric std::vector<uint32_t> Dims;
2034ba319b5SDimitry Andric if (Node->getNumOperands() != 3)
2044ba319b5SDimitry Andric return Dims;
2054ba319b5SDimitry Andric
2064ba319b5SDimitry Andric for (auto &Op : Node->operands())
2074ba319b5SDimitry Andric Dims.push_back(mdconst::extract<ConstantInt>(Op)->getZExtValue());
2084ba319b5SDimitry Andric return Dims;
2094ba319b5SDimitry Andric }
2104ba319b5SDimitry Andric
211*b5893f02SDimitry Andric Kernel::CodeProps::Metadata
getHSACodeProps(const MachineFunction & MF,const SIProgramInfo & ProgramInfo) const212*b5893f02SDimitry Andric MetadataStreamerV2::getHSACodeProps(const MachineFunction &MF,
2134ba319b5SDimitry Andric const SIProgramInfo &ProgramInfo) const {
2144ba319b5SDimitry Andric const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
2154ba319b5SDimitry Andric const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
2164ba319b5SDimitry Andric HSAMD::Kernel::CodeProps::Metadata HSACodeProps;
2174ba319b5SDimitry Andric const Function &F = MF.getFunction();
2184ba319b5SDimitry Andric
2194ba319b5SDimitry Andric assert(F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
2204ba319b5SDimitry Andric F.getCallingConv() == CallingConv::SPIR_KERNEL);
2214ba319b5SDimitry Andric
2224ba319b5SDimitry Andric unsigned MaxKernArgAlign;
2234ba319b5SDimitry Andric HSACodeProps.mKernargSegmentSize = STM.getKernArgSegmentSize(F,
2244ba319b5SDimitry Andric MaxKernArgAlign);
2254ba319b5SDimitry Andric HSACodeProps.mGroupSegmentFixedSize = ProgramInfo.LDSSize;
2264ba319b5SDimitry Andric HSACodeProps.mPrivateSegmentFixedSize = ProgramInfo.ScratchSize;
2274ba319b5SDimitry Andric HSACodeProps.mKernargSegmentAlign = std::max(MaxKernArgAlign, 4u);
2284ba319b5SDimitry Andric HSACodeProps.mWavefrontSize = STM.getWavefrontSize();
2294ba319b5SDimitry Andric HSACodeProps.mNumSGPRs = ProgramInfo.NumSGPR;
2304ba319b5SDimitry Andric HSACodeProps.mNumVGPRs = ProgramInfo.NumVGPR;
2314ba319b5SDimitry Andric HSACodeProps.mMaxFlatWorkGroupSize = MFI.getMaxFlatWorkGroupSize();
2324ba319b5SDimitry Andric HSACodeProps.mIsDynamicCallStack = ProgramInfo.DynamicCallStack;
2334ba319b5SDimitry Andric HSACodeProps.mIsXNACKEnabled = STM.isXNACKEnabled();
2344ba319b5SDimitry Andric HSACodeProps.mNumSpilledSGPRs = MFI.getNumSpilledSGPRs();
2354ba319b5SDimitry Andric HSACodeProps.mNumSpilledVGPRs = MFI.getNumSpilledVGPRs();
2364ba319b5SDimitry Andric
2374ba319b5SDimitry Andric return HSACodeProps;
2384ba319b5SDimitry Andric }
2394ba319b5SDimitry Andric
240*b5893f02SDimitry Andric Kernel::DebugProps::Metadata
getHSADebugProps(const MachineFunction & MF,const SIProgramInfo & ProgramInfo) const241*b5893f02SDimitry Andric MetadataStreamerV2::getHSADebugProps(const MachineFunction &MF,
2424ba319b5SDimitry Andric const SIProgramInfo &ProgramInfo) const {
2434ba319b5SDimitry Andric const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
2444ba319b5SDimitry Andric HSAMD::Kernel::DebugProps::Metadata HSADebugProps;
2454ba319b5SDimitry Andric
2464ba319b5SDimitry Andric if (!STM.debuggerSupported())
2474ba319b5SDimitry Andric return HSADebugProps;
2484ba319b5SDimitry Andric
2494ba319b5SDimitry Andric HSADebugProps.mDebuggerABIVersion.push_back(1);
2504ba319b5SDimitry Andric HSADebugProps.mDebuggerABIVersion.push_back(0);
2514ba319b5SDimitry Andric
2524ba319b5SDimitry Andric if (STM.debuggerEmitPrologue()) {
2534ba319b5SDimitry Andric HSADebugProps.mPrivateSegmentBufferSGPR =
2544ba319b5SDimitry Andric ProgramInfo.DebuggerPrivateSegmentBufferSGPR;
2554ba319b5SDimitry Andric HSADebugProps.mWavefrontPrivateSegmentOffsetSGPR =
2564ba319b5SDimitry Andric ProgramInfo.DebuggerWavefrontPrivateSegmentOffsetSGPR;
2574ba319b5SDimitry Andric }
2584ba319b5SDimitry Andric
2594ba319b5SDimitry Andric return HSADebugProps;
2604ba319b5SDimitry Andric }
2614ba319b5SDimitry Andric
emitVersion()262*b5893f02SDimitry Andric void MetadataStreamerV2::emitVersion() {
2634ba319b5SDimitry Andric auto &Version = HSAMetadata.mVersion;
2644ba319b5SDimitry Andric
2654ba319b5SDimitry Andric Version.push_back(VersionMajor);
2664ba319b5SDimitry Andric Version.push_back(VersionMinor);
2674ba319b5SDimitry Andric }
2684ba319b5SDimitry Andric
emitPrintf(const Module & Mod)269*b5893f02SDimitry Andric void MetadataStreamerV2::emitPrintf(const Module &Mod) {
2704ba319b5SDimitry Andric auto &Printf = HSAMetadata.mPrintf;
2714ba319b5SDimitry Andric
2724ba319b5SDimitry Andric auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
2734ba319b5SDimitry Andric if (!Node)
2744ba319b5SDimitry Andric return;
2754ba319b5SDimitry Andric
2764ba319b5SDimitry Andric for (auto Op : Node->operands())
2774ba319b5SDimitry Andric if (Op->getNumOperands())
2784ba319b5SDimitry Andric Printf.push_back(cast<MDString>(Op->getOperand(0))->getString());
2794ba319b5SDimitry Andric }
2804ba319b5SDimitry Andric
emitKernelLanguage(const Function & Func)281*b5893f02SDimitry Andric void MetadataStreamerV2::emitKernelLanguage(const Function &Func) {
2824ba319b5SDimitry Andric auto &Kernel = HSAMetadata.mKernels.back();
2834ba319b5SDimitry Andric
2844ba319b5SDimitry Andric // TODO: What about other languages?
2854ba319b5SDimitry Andric auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
2864ba319b5SDimitry Andric if (!Node || !Node->getNumOperands())
2874ba319b5SDimitry Andric return;
2884ba319b5SDimitry Andric auto Op0 = Node->getOperand(0);
2894ba319b5SDimitry Andric if (Op0->getNumOperands() <= 1)
2904ba319b5SDimitry Andric return;
2914ba319b5SDimitry Andric
2924ba319b5SDimitry Andric Kernel.mLanguage = "OpenCL C";
2934ba319b5SDimitry Andric Kernel.mLanguageVersion.push_back(
2944ba319b5SDimitry Andric mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue());
2954ba319b5SDimitry Andric Kernel.mLanguageVersion.push_back(
2964ba319b5SDimitry Andric mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue());
2974ba319b5SDimitry Andric }
2984ba319b5SDimitry Andric
emitKernelAttrs(const Function & Func)299*b5893f02SDimitry Andric void MetadataStreamerV2::emitKernelAttrs(const Function &Func) {
3004ba319b5SDimitry Andric auto &Attrs = HSAMetadata.mKernels.back().mAttrs;
3014ba319b5SDimitry Andric
3024ba319b5SDimitry Andric if (auto Node = Func.getMetadata("reqd_work_group_size"))
3034ba319b5SDimitry Andric Attrs.mReqdWorkGroupSize = getWorkGroupDimensions(Node);
3044ba319b5SDimitry Andric if (auto Node = Func.getMetadata("work_group_size_hint"))
3054ba319b5SDimitry Andric Attrs.mWorkGroupSizeHint = getWorkGroupDimensions(Node);
3064ba319b5SDimitry Andric if (auto Node = Func.getMetadata("vec_type_hint")) {
3074ba319b5SDimitry Andric Attrs.mVecTypeHint = getTypeName(
3084ba319b5SDimitry Andric cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
3094ba319b5SDimitry Andric mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue());
3104ba319b5SDimitry Andric }
3114ba319b5SDimitry Andric if (Func.hasFnAttribute("runtime-handle")) {
3124ba319b5SDimitry Andric Attrs.mRuntimeHandle =
3134ba319b5SDimitry Andric Func.getFnAttribute("runtime-handle").getValueAsString().str();
3144ba319b5SDimitry Andric }
3154ba319b5SDimitry Andric }
3164ba319b5SDimitry Andric
emitKernelArgs(const Function & Func)317*b5893f02SDimitry Andric void MetadataStreamerV2::emitKernelArgs(const Function &Func) {
3184ba319b5SDimitry Andric for (auto &Arg : Func.args())
3194ba319b5SDimitry Andric emitKernelArg(Arg);
3204ba319b5SDimitry Andric
3214ba319b5SDimitry Andric emitHiddenKernelArgs(Func);
3224ba319b5SDimitry Andric }
3234ba319b5SDimitry Andric
emitKernelArg(const Argument & Arg)324*b5893f02SDimitry Andric void MetadataStreamerV2::emitKernelArg(const Argument &Arg) {
3254ba319b5SDimitry Andric auto Func = Arg.getParent();
3264ba319b5SDimitry Andric auto ArgNo = Arg.getArgNo();
3274ba319b5SDimitry Andric const MDNode *Node;
3284ba319b5SDimitry Andric
3294ba319b5SDimitry Andric StringRef Name;
3304ba319b5SDimitry Andric Node = Func->getMetadata("kernel_arg_name");
3314ba319b5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
3324ba319b5SDimitry Andric Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
3334ba319b5SDimitry Andric else if (Arg.hasName())
3344ba319b5SDimitry Andric Name = Arg.getName();
3354ba319b5SDimitry Andric
3364ba319b5SDimitry Andric StringRef TypeName;
3374ba319b5SDimitry Andric Node = Func->getMetadata("kernel_arg_type");
3384ba319b5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
3394ba319b5SDimitry Andric TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
3404ba319b5SDimitry Andric
3414ba319b5SDimitry Andric StringRef BaseTypeName;
3424ba319b5SDimitry Andric Node = Func->getMetadata("kernel_arg_base_type");
3434ba319b5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
3444ba319b5SDimitry Andric BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
3454ba319b5SDimitry Andric
3464ba319b5SDimitry Andric StringRef AccQual;
3474ba319b5SDimitry Andric if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() &&
3484ba319b5SDimitry Andric Arg.hasNoAliasAttr()) {
3494ba319b5SDimitry Andric AccQual = "read_only";
3504ba319b5SDimitry Andric } else {
3514ba319b5SDimitry Andric Node = Func->getMetadata("kernel_arg_access_qual");
3524ba319b5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
3534ba319b5SDimitry Andric AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
3544ba319b5SDimitry Andric }
3554ba319b5SDimitry Andric
3564ba319b5SDimitry Andric StringRef TypeQual;
3574ba319b5SDimitry Andric Node = Func->getMetadata("kernel_arg_type_qual");
3584ba319b5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
3594ba319b5SDimitry Andric TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
3604ba319b5SDimitry Andric
3614ba319b5SDimitry Andric Type *Ty = Arg.getType();
3624ba319b5SDimitry Andric const DataLayout &DL = Func->getParent()->getDataLayout();
3634ba319b5SDimitry Andric
3644ba319b5SDimitry Andric unsigned PointeeAlign = 0;
3654ba319b5SDimitry Andric if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
366*b5893f02SDimitry Andric if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
3674ba319b5SDimitry Andric PointeeAlign = Arg.getParamAlignment();
3684ba319b5SDimitry Andric if (PointeeAlign == 0)
3694ba319b5SDimitry Andric PointeeAlign = DL.getABITypeAlignment(PtrTy->getElementType());
3704ba319b5SDimitry Andric }
3714ba319b5SDimitry Andric }
3724ba319b5SDimitry Andric
3734ba319b5SDimitry Andric emitKernelArg(DL, Ty, getValueKind(Arg.getType(), TypeQual, BaseTypeName),
3744ba319b5SDimitry Andric PointeeAlign, Name, TypeName, BaseTypeName, AccQual, TypeQual);
3754ba319b5SDimitry Andric }
3764ba319b5SDimitry Andric
emitKernelArg(const DataLayout & DL,Type * Ty,ValueKind ValueKind,unsigned PointeeAlign,StringRef Name,StringRef TypeName,StringRef BaseTypeName,StringRef AccQual,StringRef TypeQual)377*b5893f02SDimitry Andric void MetadataStreamerV2::emitKernelArg(const DataLayout &DL, Type *Ty,
3784ba319b5SDimitry Andric ValueKind ValueKind,
379*b5893f02SDimitry Andric unsigned PointeeAlign, StringRef Name,
380*b5893f02SDimitry Andric StringRef TypeName,
381*b5893f02SDimitry Andric StringRef BaseTypeName,
3824ba319b5SDimitry Andric StringRef AccQual, StringRef TypeQual) {
3834ba319b5SDimitry Andric HSAMetadata.mKernels.back().mArgs.push_back(Kernel::Arg::Metadata());
3844ba319b5SDimitry Andric auto &Arg = HSAMetadata.mKernels.back().mArgs.back();
3854ba319b5SDimitry Andric
3864ba319b5SDimitry Andric Arg.mName = Name;
3874ba319b5SDimitry Andric Arg.mTypeName = TypeName;
3884ba319b5SDimitry Andric Arg.mSize = DL.getTypeAllocSize(Ty);
3894ba319b5SDimitry Andric Arg.mAlign = DL.getABITypeAlignment(Ty);
3904ba319b5SDimitry Andric Arg.mValueKind = ValueKind;
3914ba319b5SDimitry Andric Arg.mValueType = getValueType(Ty, BaseTypeName);
3924ba319b5SDimitry Andric Arg.mPointeeAlign = PointeeAlign;
3934ba319b5SDimitry Andric
3944ba319b5SDimitry Andric if (auto PtrTy = dyn_cast<PointerType>(Ty))
395*b5893f02SDimitry Andric Arg.mAddrSpaceQual = getAddressSpaceQualifier(PtrTy->getAddressSpace());
3964ba319b5SDimitry Andric
3974ba319b5SDimitry Andric Arg.mAccQual = getAccessQualifier(AccQual);
3984ba319b5SDimitry Andric
3994ba319b5SDimitry Andric // TODO: Emit Arg.mActualAccQual.
4004ba319b5SDimitry Andric
4014ba319b5SDimitry Andric SmallVector<StringRef, 1> SplitTypeQuals;
4024ba319b5SDimitry Andric TypeQual.split(SplitTypeQuals, " ", -1, false);
4034ba319b5SDimitry Andric for (StringRef Key : SplitTypeQuals) {
4044ba319b5SDimitry Andric auto P = StringSwitch<bool*>(Key)
4054ba319b5SDimitry Andric .Case("const", &Arg.mIsConst)
4064ba319b5SDimitry Andric .Case("restrict", &Arg.mIsRestrict)
4074ba319b5SDimitry Andric .Case("volatile", &Arg.mIsVolatile)
4084ba319b5SDimitry Andric .Case("pipe", &Arg.mIsPipe)
4094ba319b5SDimitry Andric .Default(nullptr);
4104ba319b5SDimitry Andric if (P)
4114ba319b5SDimitry Andric *P = true;
4124ba319b5SDimitry Andric }
4134ba319b5SDimitry Andric }
4144ba319b5SDimitry Andric
emitHiddenKernelArgs(const Function & Func)415*b5893f02SDimitry Andric void MetadataStreamerV2::emitHiddenKernelArgs(const Function &Func) {
4164ba319b5SDimitry Andric int HiddenArgNumBytes =
4174ba319b5SDimitry Andric getIntegerAttribute(Func, "amdgpu-implicitarg-num-bytes", 0);
4184ba319b5SDimitry Andric
4194ba319b5SDimitry Andric if (!HiddenArgNumBytes)
4204ba319b5SDimitry Andric return;
4214ba319b5SDimitry Andric
4224ba319b5SDimitry Andric auto &DL = Func.getParent()->getDataLayout();
4234ba319b5SDimitry Andric auto Int64Ty = Type::getInt64Ty(Func.getContext());
4244ba319b5SDimitry Andric
4254ba319b5SDimitry Andric if (HiddenArgNumBytes >= 8)
4264ba319b5SDimitry Andric emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetX);
4274ba319b5SDimitry Andric if (HiddenArgNumBytes >= 16)
4284ba319b5SDimitry Andric emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetY);
4294ba319b5SDimitry Andric if (HiddenArgNumBytes >= 24)
4304ba319b5SDimitry Andric emitKernelArg(DL, Int64Ty, ValueKind::HiddenGlobalOffsetZ);
4314ba319b5SDimitry Andric
4324ba319b5SDimitry Andric auto Int8PtrTy = Type::getInt8PtrTy(Func.getContext(),
433*b5893f02SDimitry Andric AMDGPUAS::GLOBAL_ADDRESS);
4344ba319b5SDimitry Andric
4354ba319b5SDimitry Andric // Emit "printf buffer" argument if printf is used, otherwise emit dummy
4364ba319b5SDimitry Andric // "none" argument.
4374ba319b5SDimitry Andric if (HiddenArgNumBytes >= 32) {
4384ba319b5SDimitry Andric if (Func.getParent()->getNamedMetadata("llvm.printf.fmts"))
4394ba319b5SDimitry Andric emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenPrintfBuffer);
4404ba319b5SDimitry Andric else
4414ba319b5SDimitry Andric emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone);
4424ba319b5SDimitry Andric }
4434ba319b5SDimitry Andric
4444ba319b5SDimitry Andric // Emit "default queue" and "completion action" arguments if enqueue kernel is
4454ba319b5SDimitry Andric // used, otherwise emit dummy "none" arguments.
4464ba319b5SDimitry Andric if (HiddenArgNumBytes >= 48) {
4474ba319b5SDimitry Andric if (Func.hasFnAttribute("calls-enqueue-kernel")) {
4484ba319b5SDimitry Andric emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenDefaultQueue);
4494ba319b5SDimitry Andric emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenCompletionAction);
4504ba319b5SDimitry Andric } else {
4514ba319b5SDimitry Andric emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone);
4524ba319b5SDimitry Andric emitKernelArg(DL, Int8PtrTy, ValueKind::HiddenNone);
4534ba319b5SDimitry Andric }
4544ba319b5SDimitry Andric }
4554ba319b5SDimitry Andric }
4564ba319b5SDimitry Andric
emitTo(AMDGPUTargetStreamer & TargetStreamer)457*b5893f02SDimitry Andric bool MetadataStreamerV2::emitTo(AMDGPUTargetStreamer &TargetStreamer) {
458*b5893f02SDimitry Andric return TargetStreamer.EmitHSAMetadata(getHSAMetadata());
459*b5893f02SDimitry Andric }
460*b5893f02SDimitry Andric
begin(const Module & Mod)461*b5893f02SDimitry Andric void MetadataStreamerV2::begin(const Module &Mod) {
4624ba319b5SDimitry Andric emitVersion();
4634ba319b5SDimitry Andric emitPrintf(Mod);
4644ba319b5SDimitry Andric }
4654ba319b5SDimitry Andric
end()466*b5893f02SDimitry Andric void MetadataStreamerV2::end() {
4674ba319b5SDimitry Andric std::string HSAMetadataString;
4684ba319b5SDimitry Andric if (toString(HSAMetadata, HSAMetadataString))
4694ba319b5SDimitry Andric return;
4704ba319b5SDimitry Andric
4714ba319b5SDimitry Andric if (DumpHSAMetadata)
4724ba319b5SDimitry Andric dump(HSAMetadataString);
4734ba319b5SDimitry Andric if (VerifyHSAMetadata)
4744ba319b5SDimitry Andric verify(HSAMetadataString);
4754ba319b5SDimitry Andric }
4764ba319b5SDimitry Andric
emitKernel(const MachineFunction & MF,const SIProgramInfo & ProgramInfo)477*b5893f02SDimitry Andric void MetadataStreamerV2::emitKernel(const MachineFunction &MF,
478*b5893f02SDimitry Andric const SIProgramInfo &ProgramInfo) {
4794ba319b5SDimitry Andric auto &Func = MF.getFunction();
4804ba319b5SDimitry Andric if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL)
4814ba319b5SDimitry Andric return;
4824ba319b5SDimitry Andric
4834ba319b5SDimitry Andric auto CodeProps = getHSACodeProps(MF, ProgramInfo);
4844ba319b5SDimitry Andric auto DebugProps = getHSADebugProps(MF, ProgramInfo);
4854ba319b5SDimitry Andric
4864ba319b5SDimitry Andric HSAMetadata.mKernels.push_back(Kernel::Metadata());
4874ba319b5SDimitry Andric auto &Kernel = HSAMetadata.mKernels.back();
4884ba319b5SDimitry Andric
4894ba319b5SDimitry Andric Kernel.mName = Func.getName();
4904ba319b5SDimitry Andric Kernel.mSymbolName = (Twine(Func.getName()) + Twine("@kd")).str();
4914ba319b5SDimitry Andric emitKernelLanguage(Func);
4924ba319b5SDimitry Andric emitKernelAttrs(Func);
4934ba319b5SDimitry Andric emitKernelArgs(Func);
4944ba319b5SDimitry Andric HSAMetadata.mKernels.back().mCodeProps = CodeProps;
4954ba319b5SDimitry Andric HSAMetadata.mKernels.back().mDebugProps = DebugProps;
4964ba319b5SDimitry Andric }
4974ba319b5SDimitry Andric
498*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
499*b5893f02SDimitry Andric // HSAMetadataStreamerV3
500*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
501*b5893f02SDimitry Andric
dump(StringRef HSAMetadataString) const502*b5893f02SDimitry Andric void MetadataStreamerV3::dump(StringRef HSAMetadataString) const {
503*b5893f02SDimitry Andric errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
504*b5893f02SDimitry Andric }
505*b5893f02SDimitry Andric
verify(StringRef HSAMetadataString) const506*b5893f02SDimitry Andric void MetadataStreamerV3::verify(StringRef HSAMetadataString) const {
507*b5893f02SDimitry Andric errs() << "AMDGPU HSA Metadata Parser Test: ";
508*b5893f02SDimitry Andric
509*b5893f02SDimitry Andric std::shared_ptr<msgpack::Node> FromHSAMetadataString =
510*b5893f02SDimitry Andric std::make_shared<msgpack::MapNode>();
511*b5893f02SDimitry Andric
512*b5893f02SDimitry Andric yaml::Input YIn(HSAMetadataString);
513*b5893f02SDimitry Andric YIn >> FromHSAMetadataString;
514*b5893f02SDimitry Andric if (YIn.error()) {
515*b5893f02SDimitry Andric errs() << "FAIL\n";
516*b5893f02SDimitry Andric return;
517*b5893f02SDimitry Andric }
518*b5893f02SDimitry Andric
519*b5893f02SDimitry Andric std::string ToHSAMetadataString;
520*b5893f02SDimitry Andric raw_string_ostream StrOS(ToHSAMetadataString);
521*b5893f02SDimitry Andric yaml::Output YOut(StrOS);
522*b5893f02SDimitry Andric YOut << FromHSAMetadataString;
523*b5893f02SDimitry Andric
524*b5893f02SDimitry Andric errs() << (HSAMetadataString == StrOS.str() ? "PASS" : "FAIL") << '\n';
525*b5893f02SDimitry Andric if (HSAMetadataString != ToHSAMetadataString) {
526*b5893f02SDimitry Andric errs() << "Original input: " << HSAMetadataString << '\n'
527*b5893f02SDimitry Andric << "Produced output: " << StrOS.str() << '\n';
528*b5893f02SDimitry Andric }
529*b5893f02SDimitry Andric }
530*b5893f02SDimitry Andric
531*b5893f02SDimitry Andric Optional<StringRef>
getAccessQualifier(StringRef AccQual) const532*b5893f02SDimitry Andric MetadataStreamerV3::getAccessQualifier(StringRef AccQual) const {
533*b5893f02SDimitry Andric return StringSwitch<Optional<StringRef>>(AccQual)
534*b5893f02SDimitry Andric .Case("read_only", StringRef("read_only"))
535*b5893f02SDimitry Andric .Case("write_only", StringRef("write_only"))
536*b5893f02SDimitry Andric .Case("read_write", StringRef("read_write"))
537*b5893f02SDimitry Andric .Default(None);
538*b5893f02SDimitry Andric }
539*b5893f02SDimitry Andric
540*b5893f02SDimitry Andric Optional<StringRef>
getAddressSpaceQualifier(unsigned AddressSpace) const541*b5893f02SDimitry Andric MetadataStreamerV3::getAddressSpaceQualifier(unsigned AddressSpace) const {
542*b5893f02SDimitry Andric switch (AddressSpace) {
543*b5893f02SDimitry Andric case AMDGPUAS::PRIVATE_ADDRESS:
544*b5893f02SDimitry Andric return StringRef("private");
545*b5893f02SDimitry Andric case AMDGPUAS::GLOBAL_ADDRESS:
546*b5893f02SDimitry Andric return StringRef("global");
547*b5893f02SDimitry Andric case AMDGPUAS::CONSTANT_ADDRESS:
548*b5893f02SDimitry Andric return StringRef("constant");
549*b5893f02SDimitry Andric case AMDGPUAS::LOCAL_ADDRESS:
550*b5893f02SDimitry Andric return StringRef("local");
551*b5893f02SDimitry Andric case AMDGPUAS::FLAT_ADDRESS:
552*b5893f02SDimitry Andric return StringRef("generic");
553*b5893f02SDimitry Andric case AMDGPUAS::REGION_ADDRESS:
554*b5893f02SDimitry Andric return StringRef("region");
555*b5893f02SDimitry Andric default:
556*b5893f02SDimitry Andric return None;
557*b5893f02SDimitry Andric }
558*b5893f02SDimitry Andric }
559*b5893f02SDimitry Andric
getValueKind(Type * Ty,StringRef TypeQual,StringRef BaseTypeName) const560*b5893f02SDimitry Andric StringRef MetadataStreamerV3::getValueKind(Type *Ty, StringRef TypeQual,
561*b5893f02SDimitry Andric StringRef BaseTypeName) const {
562*b5893f02SDimitry Andric if (TypeQual.find("pipe") != StringRef::npos)
563*b5893f02SDimitry Andric return "pipe";
564*b5893f02SDimitry Andric
565*b5893f02SDimitry Andric return StringSwitch<StringRef>(BaseTypeName)
566*b5893f02SDimitry Andric .Case("image1d_t", "image")
567*b5893f02SDimitry Andric .Case("image1d_array_t", "image")
568*b5893f02SDimitry Andric .Case("image1d_buffer_t", "image")
569*b5893f02SDimitry Andric .Case("image2d_t", "image")
570*b5893f02SDimitry Andric .Case("image2d_array_t", "image")
571*b5893f02SDimitry Andric .Case("image2d_array_depth_t", "image")
572*b5893f02SDimitry Andric .Case("image2d_array_msaa_t", "image")
573*b5893f02SDimitry Andric .Case("image2d_array_msaa_depth_t", "image")
574*b5893f02SDimitry Andric .Case("image2d_depth_t", "image")
575*b5893f02SDimitry Andric .Case("image2d_msaa_t", "image")
576*b5893f02SDimitry Andric .Case("image2d_msaa_depth_t", "image")
577*b5893f02SDimitry Andric .Case("image3d_t", "image")
578*b5893f02SDimitry Andric .Case("sampler_t", "sampler")
579*b5893f02SDimitry Andric .Case("queue_t", "queue")
580*b5893f02SDimitry Andric .Default(isa<PointerType>(Ty)
581*b5893f02SDimitry Andric ? (Ty->getPointerAddressSpace() == AMDGPUAS::LOCAL_ADDRESS
582*b5893f02SDimitry Andric ? "dynamic_shared_pointer"
583*b5893f02SDimitry Andric : "global_buffer")
584*b5893f02SDimitry Andric : "by_value");
585*b5893f02SDimitry Andric }
586*b5893f02SDimitry Andric
getValueType(Type * Ty,StringRef TypeName) const587*b5893f02SDimitry Andric StringRef MetadataStreamerV3::getValueType(Type *Ty, StringRef TypeName) const {
588*b5893f02SDimitry Andric switch (Ty->getTypeID()) {
589*b5893f02SDimitry Andric case Type::IntegerTyID: {
590*b5893f02SDimitry Andric auto Signed = !TypeName.startswith("u");
591*b5893f02SDimitry Andric switch (Ty->getIntegerBitWidth()) {
592*b5893f02SDimitry Andric case 8:
593*b5893f02SDimitry Andric return Signed ? "i8" : "u8";
594*b5893f02SDimitry Andric case 16:
595*b5893f02SDimitry Andric return Signed ? "i16" : "u16";
596*b5893f02SDimitry Andric case 32:
597*b5893f02SDimitry Andric return Signed ? "i32" : "u32";
598*b5893f02SDimitry Andric case 64:
599*b5893f02SDimitry Andric return Signed ? "i64" : "u64";
600*b5893f02SDimitry Andric default:
601*b5893f02SDimitry Andric return "struct";
602*b5893f02SDimitry Andric }
603*b5893f02SDimitry Andric }
604*b5893f02SDimitry Andric case Type::HalfTyID:
605*b5893f02SDimitry Andric return "f16";
606*b5893f02SDimitry Andric case Type::FloatTyID:
607*b5893f02SDimitry Andric return "f32";
608*b5893f02SDimitry Andric case Type::DoubleTyID:
609*b5893f02SDimitry Andric return "f64";
610*b5893f02SDimitry Andric case Type::PointerTyID:
611*b5893f02SDimitry Andric return getValueType(Ty->getPointerElementType(), TypeName);
612*b5893f02SDimitry Andric case Type::VectorTyID:
613*b5893f02SDimitry Andric return getValueType(Ty->getVectorElementType(), TypeName);
614*b5893f02SDimitry Andric default:
615*b5893f02SDimitry Andric return "struct";
616*b5893f02SDimitry Andric }
617*b5893f02SDimitry Andric }
618*b5893f02SDimitry Andric
getTypeName(Type * Ty,bool Signed) const619*b5893f02SDimitry Andric std::string MetadataStreamerV3::getTypeName(Type *Ty, bool Signed) const {
620*b5893f02SDimitry Andric switch (Ty->getTypeID()) {
621*b5893f02SDimitry Andric case Type::IntegerTyID: {
622*b5893f02SDimitry Andric if (!Signed)
623*b5893f02SDimitry Andric return (Twine('u') + getTypeName(Ty, true)).str();
624*b5893f02SDimitry Andric
625*b5893f02SDimitry Andric auto BitWidth = Ty->getIntegerBitWidth();
626*b5893f02SDimitry Andric switch (BitWidth) {
627*b5893f02SDimitry Andric case 8:
628*b5893f02SDimitry Andric return "char";
629*b5893f02SDimitry Andric case 16:
630*b5893f02SDimitry Andric return "short";
631*b5893f02SDimitry Andric case 32:
632*b5893f02SDimitry Andric return "int";
633*b5893f02SDimitry Andric case 64:
634*b5893f02SDimitry Andric return "long";
635*b5893f02SDimitry Andric default:
636*b5893f02SDimitry Andric return (Twine('i') + Twine(BitWidth)).str();
637*b5893f02SDimitry Andric }
638*b5893f02SDimitry Andric }
639*b5893f02SDimitry Andric case Type::HalfTyID:
640*b5893f02SDimitry Andric return "half";
641*b5893f02SDimitry Andric case Type::FloatTyID:
642*b5893f02SDimitry Andric return "float";
643*b5893f02SDimitry Andric case Type::DoubleTyID:
644*b5893f02SDimitry Andric return "double";
645*b5893f02SDimitry Andric case Type::VectorTyID: {
646*b5893f02SDimitry Andric auto VecTy = cast<VectorType>(Ty);
647*b5893f02SDimitry Andric auto ElTy = VecTy->getElementType();
648*b5893f02SDimitry Andric auto NumElements = VecTy->getVectorNumElements();
649*b5893f02SDimitry Andric return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
650*b5893f02SDimitry Andric }
651*b5893f02SDimitry Andric default:
652*b5893f02SDimitry Andric return "unknown";
653*b5893f02SDimitry Andric }
654*b5893f02SDimitry Andric }
655*b5893f02SDimitry Andric
656*b5893f02SDimitry Andric std::shared_ptr<msgpack::ArrayNode>
getWorkGroupDimensions(MDNode * Node) const657*b5893f02SDimitry Andric MetadataStreamerV3::getWorkGroupDimensions(MDNode *Node) const {
658*b5893f02SDimitry Andric auto Dims = std::make_shared<msgpack::ArrayNode>();
659*b5893f02SDimitry Andric if (Node->getNumOperands() != 3)
660*b5893f02SDimitry Andric return Dims;
661*b5893f02SDimitry Andric
662*b5893f02SDimitry Andric for (auto &Op : Node->operands())
663*b5893f02SDimitry Andric Dims->push_back(std::make_shared<msgpack::ScalarNode>(
664*b5893f02SDimitry Andric mdconst::extract<ConstantInt>(Op)->getZExtValue()));
665*b5893f02SDimitry Andric return Dims;
666*b5893f02SDimitry Andric }
667*b5893f02SDimitry Andric
emitVersion()668*b5893f02SDimitry Andric void MetadataStreamerV3::emitVersion() {
669*b5893f02SDimitry Andric auto Version = std::make_shared<msgpack::ArrayNode>();
670*b5893f02SDimitry Andric Version->push_back(std::make_shared<msgpack::ScalarNode>(V3::VersionMajor));
671*b5893f02SDimitry Andric Version->push_back(std::make_shared<msgpack::ScalarNode>(V3::VersionMinor));
672*b5893f02SDimitry Andric getRootMetadata("amdhsa.version") = std::move(Version);
673*b5893f02SDimitry Andric }
674*b5893f02SDimitry Andric
emitPrintf(const Module & Mod)675*b5893f02SDimitry Andric void MetadataStreamerV3::emitPrintf(const Module &Mod) {
676*b5893f02SDimitry Andric auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
677*b5893f02SDimitry Andric if (!Node)
678*b5893f02SDimitry Andric return;
679*b5893f02SDimitry Andric
680*b5893f02SDimitry Andric auto Printf = std::make_shared<msgpack::ArrayNode>();
681*b5893f02SDimitry Andric for (auto Op : Node->operands())
682*b5893f02SDimitry Andric if (Op->getNumOperands())
683*b5893f02SDimitry Andric Printf->push_back(std::make_shared<msgpack::ScalarNode>(
684*b5893f02SDimitry Andric cast<MDString>(Op->getOperand(0))->getString()));
685*b5893f02SDimitry Andric getRootMetadata("amdhsa.printf") = std::move(Printf);
686*b5893f02SDimitry Andric }
687*b5893f02SDimitry Andric
emitKernelLanguage(const Function & Func,msgpack::MapNode & Kern)688*b5893f02SDimitry Andric void MetadataStreamerV3::emitKernelLanguage(const Function &Func,
689*b5893f02SDimitry Andric msgpack::MapNode &Kern) {
690*b5893f02SDimitry Andric // TODO: What about other languages?
691*b5893f02SDimitry Andric auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
692*b5893f02SDimitry Andric if (!Node || !Node->getNumOperands())
693*b5893f02SDimitry Andric return;
694*b5893f02SDimitry Andric auto Op0 = Node->getOperand(0);
695*b5893f02SDimitry Andric if (Op0->getNumOperands() <= 1)
696*b5893f02SDimitry Andric return;
697*b5893f02SDimitry Andric
698*b5893f02SDimitry Andric Kern[".language"] = std::make_shared<msgpack::ScalarNode>("OpenCL C");
699*b5893f02SDimitry Andric auto LanguageVersion = std::make_shared<msgpack::ArrayNode>();
700*b5893f02SDimitry Andric LanguageVersion->push_back(std::make_shared<msgpack::ScalarNode>(
701*b5893f02SDimitry Andric mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue()));
702*b5893f02SDimitry Andric LanguageVersion->push_back(std::make_shared<msgpack::ScalarNode>(
703*b5893f02SDimitry Andric mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue()));
704*b5893f02SDimitry Andric Kern[".language_version"] = std::move(LanguageVersion);
705*b5893f02SDimitry Andric }
706*b5893f02SDimitry Andric
emitKernelAttrs(const Function & Func,msgpack::MapNode & Kern)707*b5893f02SDimitry Andric void MetadataStreamerV3::emitKernelAttrs(const Function &Func,
708*b5893f02SDimitry Andric msgpack::MapNode &Kern) {
709*b5893f02SDimitry Andric
710*b5893f02SDimitry Andric if (auto Node = Func.getMetadata("reqd_work_group_size"))
711*b5893f02SDimitry Andric Kern[".reqd_workgroup_size"] = getWorkGroupDimensions(Node);
712*b5893f02SDimitry Andric if (auto Node = Func.getMetadata("work_group_size_hint"))
713*b5893f02SDimitry Andric Kern[".workgroup_size_hint"] = getWorkGroupDimensions(Node);
714*b5893f02SDimitry Andric if (auto Node = Func.getMetadata("vec_type_hint")) {
715*b5893f02SDimitry Andric Kern[".vec_type_hint"] = std::make_shared<msgpack::ScalarNode>(getTypeName(
716*b5893f02SDimitry Andric cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
717*b5893f02SDimitry Andric mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue()));
718*b5893f02SDimitry Andric }
719*b5893f02SDimitry Andric if (Func.hasFnAttribute("runtime-handle")) {
720*b5893f02SDimitry Andric Kern[".device_enqueue_symbol"] = std::make_shared<msgpack::ScalarNode>(
721*b5893f02SDimitry Andric Func.getFnAttribute("runtime-handle").getValueAsString().str());
722*b5893f02SDimitry Andric }
723*b5893f02SDimitry Andric }
724*b5893f02SDimitry Andric
emitKernelArgs(const Function & Func,msgpack::MapNode & Kern)725*b5893f02SDimitry Andric void MetadataStreamerV3::emitKernelArgs(const Function &Func,
726*b5893f02SDimitry Andric msgpack::MapNode &Kern) {
727*b5893f02SDimitry Andric unsigned Offset = 0;
728*b5893f02SDimitry Andric auto Args = std::make_shared<msgpack::ArrayNode>();
729*b5893f02SDimitry Andric for (auto &Arg : Func.args())
730*b5893f02SDimitry Andric emitKernelArg(Arg, Offset, *Args);
731*b5893f02SDimitry Andric
732*b5893f02SDimitry Andric emitHiddenKernelArgs(Func, Offset, *Args);
733*b5893f02SDimitry Andric
734*b5893f02SDimitry Andric // TODO: What about other languages?
735*b5893f02SDimitry Andric if (Func.getParent()->getNamedMetadata("opencl.ocl.version")) {
736*b5893f02SDimitry Andric auto &DL = Func.getParent()->getDataLayout();
737*b5893f02SDimitry Andric auto Int64Ty = Type::getInt64Ty(Func.getContext());
738*b5893f02SDimitry Andric
739*b5893f02SDimitry Andric emitKernelArg(DL, Int64Ty, "hidden_global_offset_x", Offset, *Args);
740*b5893f02SDimitry Andric emitKernelArg(DL, Int64Ty, "hidden_global_offset_y", Offset, *Args);
741*b5893f02SDimitry Andric emitKernelArg(DL, Int64Ty, "hidden_global_offset_z", Offset, *Args);
742*b5893f02SDimitry Andric
743*b5893f02SDimitry Andric auto Int8PtrTy =
744*b5893f02SDimitry Andric Type::getInt8PtrTy(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
745*b5893f02SDimitry Andric
746*b5893f02SDimitry Andric // Emit "printf buffer" argument if printf is used, otherwise emit dummy
747*b5893f02SDimitry Andric // "none" argument.
748*b5893f02SDimitry Andric if (Func.getParent()->getNamedMetadata("llvm.printf.fmts"))
749*b5893f02SDimitry Andric emitKernelArg(DL, Int8PtrTy, "hidden_printf_buffer", Offset, *Args);
750*b5893f02SDimitry Andric else
751*b5893f02SDimitry Andric emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, *Args);
752*b5893f02SDimitry Andric
753*b5893f02SDimitry Andric // Emit "default queue" and "completion action" arguments if enqueue kernel
754*b5893f02SDimitry Andric // is used, otherwise emit dummy "none" arguments.
755*b5893f02SDimitry Andric if (Func.hasFnAttribute("calls-enqueue-kernel")) {
756*b5893f02SDimitry Andric emitKernelArg(DL, Int8PtrTy, "hidden_default_queue", Offset, *Args);
757*b5893f02SDimitry Andric emitKernelArg(DL, Int8PtrTy, "hidden_completion_action", Offset, *Args);
758*b5893f02SDimitry Andric } else {
759*b5893f02SDimitry Andric emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, *Args);
760*b5893f02SDimitry Andric emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, *Args);
761*b5893f02SDimitry Andric }
762*b5893f02SDimitry Andric }
763*b5893f02SDimitry Andric
764*b5893f02SDimitry Andric Kern[".args"] = std::move(Args);
765*b5893f02SDimitry Andric }
766*b5893f02SDimitry Andric
emitKernelArg(const Argument & Arg,unsigned & Offset,msgpack::ArrayNode & Args)767*b5893f02SDimitry Andric void MetadataStreamerV3::emitKernelArg(const Argument &Arg, unsigned &Offset,
768*b5893f02SDimitry Andric msgpack::ArrayNode &Args) {
769*b5893f02SDimitry Andric auto Func = Arg.getParent();
770*b5893f02SDimitry Andric auto ArgNo = Arg.getArgNo();
771*b5893f02SDimitry Andric const MDNode *Node;
772*b5893f02SDimitry Andric
773*b5893f02SDimitry Andric StringRef Name;
774*b5893f02SDimitry Andric Node = Func->getMetadata("kernel_arg_name");
775*b5893f02SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
776*b5893f02SDimitry Andric Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
777*b5893f02SDimitry Andric else if (Arg.hasName())
778*b5893f02SDimitry Andric Name = Arg.getName();
779*b5893f02SDimitry Andric
780*b5893f02SDimitry Andric StringRef TypeName;
781*b5893f02SDimitry Andric Node = Func->getMetadata("kernel_arg_type");
782*b5893f02SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
783*b5893f02SDimitry Andric TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
784*b5893f02SDimitry Andric
785*b5893f02SDimitry Andric StringRef BaseTypeName;
786*b5893f02SDimitry Andric Node = Func->getMetadata("kernel_arg_base_type");
787*b5893f02SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
788*b5893f02SDimitry Andric BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
789*b5893f02SDimitry Andric
790*b5893f02SDimitry Andric StringRef AccQual;
791*b5893f02SDimitry Andric if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() &&
792*b5893f02SDimitry Andric Arg.hasNoAliasAttr()) {
793*b5893f02SDimitry Andric AccQual = "read_only";
794*b5893f02SDimitry Andric } else {
795*b5893f02SDimitry Andric Node = Func->getMetadata("kernel_arg_access_qual");
796*b5893f02SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
797*b5893f02SDimitry Andric AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
798*b5893f02SDimitry Andric }
799*b5893f02SDimitry Andric
800*b5893f02SDimitry Andric StringRef TypeQual;
801*b5893f02SDimitry Andric Node = Func->getMetadata("kernel_arg_type_qual");
802*b5893f02SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
803*b5893f02SDimitry Andric TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
804*b5893f02SDimitry Andric
805*b5893f02SDimitry Andric Type *Ty = Arg.getType();
806*b5893f02SDimitry Andric const DataLayout &DL = Func->getParent()->getDataLayout();
807*b5893f02SDimitry Andric
808*b5893f02SDimitry Andric unsigned PointeeAlign = 0;
809*b5893f02SDimitry Andric if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
810*b5893f02SDimitry Andric if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
811*b5893f02SDimitry Andric PointeeAlign = Arg.getParamAlignment();
812*b5893f02SDimitry Andric if (PointeeAlign == 0)
813*b5893f02SDimitry Andric PointeeAlign = DL.getABITypeAlignment(PtrTy->getElementType());
814*b5893f02SDimitry Andric }
815*b5893f02SDimitry Andric }
816*b5893f02SDimitry Andric
817*b5893f02SDimitry Andric emitKernelArg(Func->getParent()->getDataLayout(), Arg.getType(),
818*b5893f02SDimitry Andric getValueKind(Arg.getType(), TypeQual, BaseTypeName), Offset,
819*b5893f02SDimitry Andric Args, PointeeAlign, Name, TypeName, BaseTypeName, AccQual,
820*b5893f02SDimitry Andric TypeQual);
821*b5893f02SDimitry Andric }
822*b5893f02SDimitry Andric
emitKernelArg(const DataLayout & DL,Type * Ty,StringRef ValueKind,unsigned & Offset,msgpack::ArrayNode & Args,unsigned PointeeAlign,StringRef Name,StringRef TypeName,StringRef BaseTypeName,StringRef AccQual,StringRef TypeQual)823*b5893f02SDimitry Andric void MetadataStreamerV3::emitKernelArg(const DataLayout &DL, Type *Ty,
824*b5893f02SDimitry Andric StringRef ValueKind, unsigned &Offset,
825*b5893f02SDimitry Andric msgpack::ArrayNode &Args,
826*b5893f02SDimitry Andric unsigned PointeeAlign, StringRef Name,
827*b5893f02SDimitry Andric StringRef TypeName,
828*b5893f02SDimitry Andric StringRef BaseTypeName,
829*b5893f02SDimitry Andric StringRef AccQual, StringRef TypeQual) {
830*b5893f02SDimitry Andric auto ArgPtr = std::make_shared<msgpack::MapNode>();
831*b5893f02SDimitry Andric auto &Arg = *ArgPtr;
832*b5893f02SDimitry Andric
833*b5893f02SDimitry Andric if (!Name.empty())
834*b5893f02SDimitry Andric Arg[".name"] = std::make_shared<msgpack::ScalarNode>(Name);
835*b5893f02SDimitry Andric if (!TypeName.empty())
836*b5893f02SDimitry Andric Arg[".type_name"] = std::make_shared<msgpack::ScalarNode>(TypeName);
837*b5893f02SDimitry Andric auto Size = DL.getTypeAllocSize(Ty);
838*b5893f02SDimitry Andric auto Align = DL.getABITypeAlignment(Ty);
839*b5893f02SDimitry Andric Arg[".size"] = std::make_shared<msgpack::ScalarNode>(Size);
840*b5893f02SDimitry Andric Offset = alignTo(Offset, Align);
841*b5893f02SDimitry Andric Arg[".offset"] = std::make_shared<msgpack::ScalarNode>(Offset);
842*b5893f02SDimitry Andric Offset += Size;
843*b5893f02SDimitry Andric Arg[".value_kind"] = std::make_shared<msgpack::ScalarNode>(ValueKind);
844*b5893f02SDimitry Andric Arg[".value_type"] =
845*b5893f02SDimitry Andric std::make_shared<msgpack::ScalarNode>(getValueType(Ty, BaseTypeName));
846*b5893f02SDimitry Andric if (PointeeAlign)
847*b5893f02SDimitry Andric Arg[".pointee_align"] = std::make_shared<msgpack::ScalarNode>(PointeeAlign);
848*b5893f02SDimitry Andric
849*b5893f02SDimitry Andric if (auto PtrTy = dyn_cast<PointerType>(Ty))
850*b5893f02SDimitry Andric if (auto Qualifier = getAddressSpaceQualifier(PtrTy->getAddressSpace()))
851*b5893f02SDimitry Andric Arg[".address_space"] = std::make_shared<msgpack::ScalarNode>(*Qualifier);
852*b5893f02SDimitry Andric
853*b5893f02SDimitry Andric if (auto AQ = getAccessQualifier(AccQual))
854*b5893f02SDimitry Andric Arg[".access"] = std::make_shared<msgpack::ScalarNode>(*AQ);
855*b5893f02SDimitry Andric
856*b5893f02SDimitry Andric // TODO: Emit Arg[".actual_access"].
857*b5893f02SDimitry Andric
858*b5893f02SDimitry Andric SmallVector<StringRef, 1> SplitTypeQuals;
859*b5893f02SDimitry Andric TypeQual.split(SplitTypeQuals, " ", -1, false);
860*b5893f02SDimitry Andric for (StringRef Key : SplitTypeQuals) {
861*b5893f02SDimitry Andric if (Key == "const")
862*b5893f02SDimitry Andric Arg[".is_const"] = std::make_shared<msgpack::ScalarNode>(true);
863*b5893f02SDimitry Andric else if (Key == "restrict")
864*b5893f02SDimitry Andric Arg[".is_restrict"] = std::make_shared<msgpack::ScalarNode>(true);
865*b5893f02SDimitry Andric else if (Key == "volatile")
866*b5893f02SDimitry Andric Arg[".is_volatile"] = std::make_shared<msgpack::ScalarNode>(true);
867*b5893f02SDimitry Andric else if (Key == "pipe")
868*b5893f02SDimitry Andric Arg[".is_pipe"] = std::make_shared<msgpack::ScalarNode>(true);
869*b5893f02SDimitry Andric }
870*b5893f02SDimitry Andric
871*b5893f02SDimitry Andric Args.push_back(std::move(ArgPtr));
872*b5893f02SDimitry Andric }
873*b5893f02SDimitry Andric
emitHiddenKernelArgs(const Function & Func,unsigned & Offset,msgpack::ArrayNode & Args)874*b5893f02SDimitry Andric void MetadataStreamerV3::emitHiddenKernelArgs(const Function &Func,
875*b5893f02SDimitry Andric unsigned &Offset,
876*b5893f02SDimitry Andric msgpack::ArrayNode &Args) {
877*b5893f02SDimitry Andric int HiddenArgNumBytes =
878*b5893f02SDimitry Andric getIntegerAttribute(Func, "amdgpu-implicitarg-num-bytes", 0);
879*b5893f02SDimitry Andric
880*b5893f02SDimitry Andric if (!HiddenArgNumBytes)
881*b5893f02SDimitry Andric return;
882*b5893f02SDimitry Andric
883*b5893f02SDimitry Andric auto &DL = Func.getParent()->getDataLayout();
884*b5893f02SDimitry Andric auto Int64Ty = Type::getInt64Ty(Func.getContext());
885*b5893f02SDimitry Andric
886*b5893f02SDimitry Andric if (HiddenArgNumBytes >= 8)
887*b5893f02SDimitry Andric emitKernelArg(DL, Int64Ty, "hidden_global_offset_x", Offset, Args);
888*b5893f02SDimitry Andric if (HiddenArgNumBytes >= 16)
889*b5893f02SDimitry Andric emitKernelArg(DL, Int64Ty, "hidden_global_offset_y", Offset, Args);
890*b5893f02SDimitry Andric if (HiddenArgNumBytes >= 24)
891*b5893f02SDimitry Andric emitKernelArg(DL, Int64Ty, "hidden_global_offset_z", Offset, Args);
892*b5893f02SDimitry Andric
893*b5893f02SDimitry Andric auto Int8PtrTy =
894*b5893f02SDimitry Andric Type::getInt8PtrTy(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
895*b5893f02SDimitry Andric
896*b5893f02SDimitry Andric // Emit "printf buffer" argument if printf is used, otherwise emit dummy
897*b5893f02SDimitry Andric // "none" argument.
898*b5893f02SDimitry Andric if (HiddenArgNumBytes >= 32) {
899*b5893f02SDimitry Andric if (Func.getParent()->getNamedMetadata("llvm.printf.fmts"))
900*b5893f02SDimitry Andric emitKernelArg(DL, Int8PtrTy, "hidden_printf_buffer", Offset, Args);
901*b5893f02SDimitry Andric else
902*b5893f02SDimitry Andric emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, Args);
903*b5893f02SDimitry Andric }
904*b5893f02SDimitry Andric
905*b5893f02SDimitry Andric // Emit "default queue" and "completion action" arguments if enqueue kernel is
906*b5893f02SDimitry Andric // used, otherwise emit dummy "none" arguments.
907*b5893f02SDimitry Andric if (HiddenArgNumBytes >= 48) {
908*b5893f02SDimitry Andric if (Func.hasFnAttribute("calls-enqueue-kernel")) {
909*b5893f02SDimitry Andric emitKernelArg(DL, Int8PtrTy, "hidden_default_queue", Offset, Args);
910*b5893f02SDimitry Andric emitKernelArg(DL, Int8PtrTy, "hidden_completion_action", Offset, Args);
911*b5893f02SDimitry Andric } else {
912*b5893f02SDimitry Andric emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, Args);
913*b5893f02SDimitry Andric emitKernelArg(DL, Int8PtrTy, "hidden_none", Offset, Args);
914*b5893f02SDimitry Andric }
915*b5893f02SDimitry Andric }
916*b5893f02SDimitry Andric }
917*b5893f02SDimitry Andric
918*b5893f02SDimitry Andric std::shared_ptr<msgpack::MapNode>
getHSAKernelProps(const MachineFunction & MF,const SIProgramInfo & ProgramInfo) const919*b5893f02SDimitry Andric MetadataStreamerV3::getHSAKernelProps(const MachineFunction &MF,
920*b5893f02SDimitry Andric const SIProgramInfo &ProgramInfo) const {
921*b5893f02SDimitry Andric const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
922*b5893f02SDimitry Andric const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
923*b5893f02SDimitry Andric const Function &F = MF.getFunction();
924*b5893f02SDimitry Andric
925*b5893f02SDimitry Andric auto HSAKernelProps = std::make_shared<msgpack::MapNode>();
926*b5893f02SDimitry Andric auto &Kern = *HSAKernelProps;
927*b5893f02SDimitry Andric
928*b5893f02SDimitry Andric unsigned MaxKernArgAlign;
929*b5893f02SDimitry Andric Kern[".kernarg_segment_size"] = std::make_shared<msgpack::ScalarNode>(
930*b5893f02SDimitry Andric STM.getKernArgSegmentSize(F, MaxKernArgAlign));
931*b5893f02SDimitry Andric Kern[".group_segment_fixed_size"] =
932*b5893f02SDimitry Andric std::make_shared<msgpack::ScalarNode>(ProgramInfo.LDSSize);
933*b5893f02SDimitry Andric Kern[".private_segment_fixed_size"] =
934*b5893f02SDimitry Andric std::make_shared<msgpack::ScalarNode>(ProgramInfo.ScratchSize);
935*b5893f02SDimitry Andric Kern[".kernarg_segment_align"] =
936*b5893f02SDimitry Andric std::make_shared<msgpack::ScalarNode>(std::max(uint32_t(4), MaxKernArgAlign));
937*b5893f02SDimitry Andric Kern[".wavefront_size"] =
938*b5893f02SDimitry Andric std::make_shared<msgpack::ScalarNode>(STM.getWavefrontSize());
939*b5893f02SDimitry Andric Kern[".sgpr_count"] = std::make_shared<msgpack::ScalarNode>(ProgramInfo.NumSGPR);
940*b5893f02SDimitry Andric Kern[".vgpr_count"] = std::make_shared<msgpack::ScalarNode>(ProgramInfo.NumVGPR);
941*b5893f02SDimitry Andric Kern[".max_flat_workgroup_size"] =
942*b5893f02SDimitry Andric std::make_shared<msgpack::ScalarNode>(MFI.getMaxFlatWorkGroupSize());
943*b5893f02SDimitry Andric Kern[".sgpr_spill_count"] =
944*b5893f02SDimitry Andric std::make_shared<msgpack::ScalarNode>(MFI.getNumSpilledSGPRs());
945*b5893f02SDimitry Andric Kern[".vgpr_spill_count"] =
946*b5893f02SDimitry Andric std::make_shared<msgpack::ScalarNode>(MFI.getNumSpilledVGPRs());
947*b5893f02SDimitry Andric
948*b5893f02SDimitry Andric return HSAKernelProps;
949*b5893f02SDimitry Andric }
950*b5893f02SDimitry Andric
emitTo(AMDGPUTargetStreamer & TargetStreamer)951*b5893f02SDimitry Andric bool MetadataStreamerV3::emitTo(AMDGPUTargetStreamer &TargetStreamer) {
952*b5893f02SDimitry Andric return TargetStreamer.EmitHSAMetadata(getHSAMetadataRoot(), true);
953*b5893f02SDimitry Andric }
954*b5893f02SDimitry Andric
begin(const Module & Mod)955*b5893f02SDimitry Andric void MetadataStreamerV3::begin(const Module &Mod) {
956*b5893f02SDimitry Andric emitVersion();
957*b5893f02SDimitry Andric emitPrintf(Mod);
958*b5893f02SDimitry Andric getRootMetadata("amdhsa.kernels").reset(new msgpack::ArrayNode());
959*b5893f02SDimitry Andric }
960*b5893f02SDimitry Andric
end()961*b5893f02SDimitry Andric void MetadataStreamerV3::end() {
962*b5893f02SDimitry Andric std::string HSAMetadataString;
963*b5893f02SDimitry Andric raw_string_ostream StrOS(HSAMetadataString);
964*b5893f02SDimitry Andric yaml::Output YOut(StrOS);
965*b5893f02SDimitry Andric YOut << HSAMetadataRoot;
966*b5893f02SDimitry Andric
967*b5893f02SDimitry Andric if (DumpHSAMetadata)
968*b5893f02SDimitry Andric dump(StrOS.str());
969*b5893f02SDimitry Andric if (VerifyHSAMetadata)
970*b5893f02SDimitry Andric verify(StrOS.str());
971*b5893f02SDimitry Andric }
972*b5893f02SDimitry Andric
emitKernel(const MachineFunction & MF,const SIProgramInfo & ProgramInfo)973*b5893f02SDimitry Andric void MetadataStreamerV3::emitKernel(const MachineFunction &MF,
974*b5893f02SDimitry Andric const SIProgramInfo &ProgramInfo) {
975*b5893f02SDimitry Andric auto &Func = MF.getFunction();
976*b5893f02SDimitry Andric auto KernelProps = getHSAKernelProps(MF, ProgramInfo);
977*b5893f02SDimitry Andric
978*b5893f02SDimitry Andric assert(Func.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
979*b5893f02SDimitry Andric Func.getCallingConv() == CallingConv::SPIR_KERNEL);
980*b5893f02SDimitry Andric
981*b5893f02SDimitry Andric auto &KernelsNode = getRootMetadata("amdhsa.kernels");
982*b5893f02SDimitry Andric auto Kernels = cast<msgpack::ArrayNode>(KernelsNode.get());
983*b5893f02SDimitry Andric
984*b5893f02SDimitry Andric {
985*b5893f02SDimitry Andric auto &Kern = *KernelProps;
986*b5893f02SDimitry Andric Kern[".name"] = std::make_shared<msgpack::ScalarNode>(Func.getName());
987*b5893f02SDimitry Andric Kern[".symbol"] = std::make_shared<msgpack::ScalarNode>(
988*b5893f02SDimitry Andric (Twine(Func.getName()) + Twine(".kd")).str());
989*b5893f02SDimitry Andric emitKernelLanguage(Func, Kern);
990*b5893f02SDimitry Andric emitKernelAttrs(Func, Kern);
991*b5893f02SDimitry Andric emitKernelArgs(Func, Kern);
992*b5893f02SDimitry Andric }
993*b5893f02SDimitry Andric
994*b5893f02SDimitry Andric Kernels->push_back(std::move(KernelProps));
995*b5893f02SDimitry Andric }
996*b5893f02SDimitry Andric
9974ba319b5SDimitry Andric } // end namespace HSAMD
9984ba319b5SDimitry Andric } // end namespace AMDGPU
9994ba319b5SDimitry Andric } // end namespace llvm
1000