10b57cec5SDimitry Andric //===--- AMDGPUHSAMetadataStreamer.cpp --------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// AMDGPU HSA Metadata Streamer.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric #include "AMDGPUHSAMetadataStreamer.h"
160b57cec5SDimitry Andric #include "AMDGPU.h"
17af732203SDimitry Andric #include "GCNSubtarget.h"
180b57cec5SDimitry Andric #include "MCTargetDesc/AMDGPUTargetStreamer.h"
190b57cec5SDimitry Andric #include "SIMachineFunctionInfo.h"
200b57cec5SDimitry Andric #include "SIProgramInfo.h"
210b57cec5SDimitry Andric #include "llvm/IR/Module.h"
22af732203SDimitry Andric using namespace llvm;
23af732203SDimitry Andric
getArgumentTypeAlign(const Argument & Arg,const DataLayout & DL)24af732203SDimitry Andric static std::pair<Type *, Align> getArgumentTypeAlign(const Argument &Arg,
25af732203SDimitry Andric const DataLayout &DL) {
26af732203SDimitry Andric Type *Ty = Arg.getType();
27af732203SDimitry Andric MaybeAlign ArgAlign;
28af732203SDimitry Andric if (Arg.hasByRefAttr()) {
29af732203SDimitry Andric Ty = Arg.getParamByRefType();
30af732203SDimitry Andric ArgAlign = Arg.getParamAlign();
31af732203SDimitry Andric }
32af732203SDimitry Andric
33af732203SDimitry Andric if (!ArgAlign)
34af732203SDimitry Andric ArgAlign = DL.getABITypeAlign(Ty);
35af732203SDimitry Andric
36af732203SDimitry Andric return std::make_pair(Ty, *ArgAlign);
37af732203SDimitry Andric }
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric namespace llvm {
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric static cl::opt<bool> DumpHSAMetadata(
420b57cec5SDimitry Andric "amdgpu-dump-hsa-metadata",
430b57cec5SDimitry Andric cl::desc("Dump AMDGPU HSA Metadata"));
440b57cec5SDimitry Andric static cl::opt<bool> VerifyHSAMetadata(
450b57cec5SDimitry Andric "amdgpu-verify-hsa-metadata",
460b57cec5SDimitry Andric cl::desc("Verify AMDGPU HSA Metadata"));
470b57cec5SDimitry Andric
480b57cec5SDimitry Andric namespace AMDGPU {
490b57cec5SDimitry Andric namespace HSAMD {
500b57cec5SDimitry Andric
510b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
520b57cec5SDimitry Andric // HSAMetadataStreamerV2
530b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
dump(StringRef HSAMetadataString) const540b57cec5SDimitry Andric void MetadataStreamerV2::dump(StringRef HSAMetadataString) const {
550b57cec5SDimitry Andric errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric
verify(StringRef HSAMetadataString) const580b57cec5SDimitry Andric void MetadataStreamerV2::verify(StringRef HSAMetadataString) const {
590b57cec5SDimitry Andric errs() << "AMDGPU HSA Metadata Parser Test: ";
600b57cec5SDimitry Andric
610b57cec5SDimitry Andric HSAMD::Metadata FromHSAMetadataString;
62af732203SDimitry Andric if (fromString(HSAMetadataString, FromHSAMetadataString)) {
630b57cec5SDimitry Andric errs() << "FAIL\n";
640b57cec5SDimitry Andric return;
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric std::string ToHSAMetadataString;
680b57cec5SDimitry Andric if (toString(FromHSAMetadataString, ToHSAMetadataString)) {
690b57cec5SDimitry Andric errs() << "FAIL\n";
700b57cec5SDimitry Andric return;
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric
730b57cec5SDimitry Andric errs() << (HSAMetadataString == ToHSAMetadataString ? "PASS" : "FAIL")
740b57cec5SDimitry Andric << '\n';
750b57cec5SDimitry Andric if (HSAMetadataString != ToHSAMetadataString) {
760b57cec5SDimitry Andric errs() << "Original input: " << HSAMetadataString << '\n'
770b57cec5SDimitry Andric << "Produced output: " << ToHSAMetadataString << '\n';
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric
810b57cec5SDimitry Andric AccessQualifier
getAccessQualifier(StringRef AccQual) const820b57cec5SDimitry Andric MetadataStreamerV2::getAccessQualifier(StringRef AccQual) const {
830b57cec5SDimitry Andric if (AccQual.empty())
840b57cec5SDimitry Andric return AccessQualifier::Unknown;
850b57cec5SDimitry Andric
860b57cec5SDimitry Andric return StringSwitch<AccessQualifier>(AccQual)
870b57cec5SDimitry Andric .Case("read_only", AccessQualifier::ReadOnly)
880b57cec5SDimitry Andric .Case("write_only", AccessQualifier::WriteOnly)
890b57cec5SDimitry Andric .Case("read_write", AccessQualifier::ReadWrite)
900b57cec5SDimitry Andric .Default(AccessQualifier::Default);
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric AddressSpaceQualifier
getAddressSpaceQualifier(unsigned AddressSpace) const940b57cec5SDimitry Andric MetadataStreamerV2::getAddressSpaceQualifier(
950b57cec5SDimitry Andric unsigned AddressSpace) const {
960b57cec5SDimitry Andric switch (AddressSpace) {
970b57cec5SDimitry Andric case AMDGPUAS::PRIVATE_ADDRESS:
980b57cec5SDimitry Andric return AddressSpaceQualifier::Private;
990b57cec5SDimitry Andric case AMDGPUAS::GLOBAL_ADDRESS:
1000b57cec5SDimitry Andric return AddressSpaceQualifier::Global;
1010b57cec5SDimitry Andric case AMDGPUAS::CONSTANT_ADDRESS:
1020b57cec5SDimitry Andric return AddressSpaceQualifier::Constant;
1030b57cec5SDimitry Andric case AMDGPUAS::LOCAL_ADDRESS:
1040b57cec5SDimitry Andric return AddressSpaceQualifier::Local;
1050b57cec5SDimitry Andric case AMDGPUAS::FLAT_ADDRESS:
1060b57cec5SDimitry Andric return AddressSpaceQualifier::Generic;
1070b57cec5SDimitry Andric case AMDGPUAS::REGION_ADDRESS:
1080b57cec5SDimitry Andric return AddressSpaceQualifier::Region;
1090b57cec5SDimitry Andric default:
1100b57cec5SDimitry Andric return AddressSpaceQualifier::Unknown;
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric
getValueKind(Type * Ty,StringRef TypeQual,StringRef BaseTypeName) const1140b57cec5SDimitry Andric ValueKind MetadataStreamerV2::getValueKind(Type *Ty, StringRef TypeQual,
1150b57cec5SDimitry Andric StringRef BaseTypeName) const {
1160b57cec5SDimitry Andric if (TypeQual.find("pipe") != StringRef::npos)
1170b57cec5SDimitry Andric return ValueKind::Pipe;
1180b57cec5SDimitry Andric
1190b57cec5SDimitry Andric return StringSwitch<ValueKind>(BaseTypeName)
1200b57cec5SDimitry Andric .Case("image1d_t", ValueKind::Image)
1210b57cec5SDimitry Andric .Case("image1d_array_t", ValueKind::Image)
1220b57cec5SDimitry Andric .Case("image1d_buffer_t", ValueKind::Image)
1230b57cec5SDimitry Andric .Case("image2d_t", ValueKind::Image)
1240b57cec5SDimitry Andric .Case("image2d_array_t", ValueKind::Image)
1250b57cec5SDimitry Andric .Case("image2d_array_depth_t", ValueKind::Image)
1260b57cec5SDimitry Andric .Case("image2d_array_msaa_t", ValueKind::Image)
1270b57cec5SDimitry Andric .Case("image2d_array_msaa_depth_t", ValueKind::Image)
1280b57cec5SDimitry Andric .Case("image2d_depth_t", ValueKind::Image)
1290b57cec5SDimitry Andric .Case("image2d_msaa_t", ValueKind::Image)
1300b57cec5SDimitry Andric .Case("image2d_msaa_depth_t", ValueKind::Image)
1310b57cec5SDimitry Andric .Case("image3d_t", ValueKind::Image)
1320b57cec5SDimitry Andric .Case("sampler_t", ValueKind::Sampler)
1330b57cec5SDimitry Andric .Case("queue_t", ValueKind::Queue)
1340b57cec5SDimitry Andric .Default(isa<PointerType>(Ty) ?
1350b57cec5SDimitry Andric (Ty->getPointerAddressSpace() ==
1360b57cec5SDimitry Andric AMDGPUAS::LOCAL_ADDRESS ?
1370b57cec5SDimitry Andric ValueKind::DynamicSharedPointer :
1380b57cec5SDimitry Andric ValueKind::GlobalBuffer) :
1390b57cec5SDimitry Andric ValueKind::ByValue);
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric
getTypeName(Type * Ty,bool Signed) const1420b57cec5SDimitry Andric std::string MetadataStreamerV2::getTypeName(Type *Ty, bool Signed) const {
1430b57cec5SDimitry Andric switch (Ty->getTypeID()) {
1440b57cec5SDimitry Andric case Type::IntegerTyID: {
1450b57cec5SDimitry Andric if (!Signed)
1460b57cec5SDimitry Andric return (Twine('u') + getTypeName(Ty, true)).str();
1470b57cec5SDimitry Andric
1480b57cec5SDimitry Andric auto BitWidth = Ty->getIntegerBitWidth();
1490b57cec5SDimitry Andric switch (BitWidth) {
1500b57cec5SDimitry Andric case 8:
1510b57cec5SDimitry Andric return "char";
1520b57cec5SDimitry Andric case 16:
1530b57cec5SDimitry Andric return "short";
1540b57cec5SDimitry Andric case 32:
1550b57cec5SDimitry Andric return "int";
1560b57cec5SDimitry Andric case 64:
1570b57cec5SDimitry Andric return "long";
1580b57cec5SDimitry Andric default:
1590b57cec5SDimitry Andric return (Twine('i') + Twine(BitWidth)).str();
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric case Type::HalfTyID:
1630b57cec5SDimitry Andric return "half";
1640b57cec5SDimitry Andric case Type::FloatTyID:
1650b57cec5SDimitry Andric return "float";
1660b57cec5SDimitry Andric case Type::DoubleTyID:
1670b57cec5SDimitry Andric return "double";
1685ffd83dbSDimitry Andric case Type::FixedVectorTyID: {
1695ffd83dbSDimitry Andric auto VecTy = cast<FixedVectorType>(Ty);
1700b57cec5SDimitry Andric auto ElTy = VecTy->getElementType();
1715ffd83dbSDimitry Andric auto NumElements = VecTy->getNumElements();
1720b57cec5SDimitry Andric return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric default:
1750b57cec5SDimitry Andric return "unknown";
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andric std::vector<uint32_t>
getWorkGroupDimensions(MDNode * Node) const1800b57cec5SDimitry Andric MetadataStreamerV2::getWorkGroupDimensions(MDNode *Node) const {
1810b57cec5SDimitry Andric std::vector<uint32_t> Dims;
1820b57cec5SDimitry Andric if (Node->getNumOperands() != 3)
1830b57cec5SDimitry Andric return Dims;
1840b57cec5SDimitry Andric
1850b57cec5SDimitry Andric for (auto &Op : Node->operands())
1860b57cec5SDimitry Andric Dims.push_back(mdconst::extract<ConstantInt>(Op)->getZExtValue());
1870b57cec5SDimitry Andric return Dims;
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric
1900b57cec5SDimitry Andric Kernel::CodeProps::Metadata
getHSACodeProps(const MachineFunction & MF,const SIProgramInfo & ProgramInfo) const1910b57cec5SDimitry Andric MetadataStreamerV2::getHSACodeProps(const MachineFunction &MF,
1920b57cec5SDimitry Andric const SIProgramInfo &ProgramInfo) const {
1930b57cec5SDimitry Andric const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1940b57cec5SDimitry Andric const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
1950b57cec5SDimitry Andric HSAMD::Kernel::CodeProps::Metadata HSACodeProps;
1960b57cec5SDimitry Andric const Function &F = MF.getFunction();
1970b57cec5SDimitry Andric
1980b57cec5SDimitry Andric assert(F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
1990b57cec5SDimitry Andric F.getCallingConv() == CallingConv::SPIR_KERNEL);
2000b57cec5SDimitry Andric
2018bcb0991SDimitry Andric Align MaxKernArgAlign;
2020b57cec5SDimitry Andric HSACodeProps.mKernargSegmentSize = STM.getKernArgSegmentSize(F,
2030b57cec5SDimitry Andric MaxKernArgAlign);
2040b57cec5SDimitry Andric HSACodeProps.mGroupSegmentFixedSize = ProgramInfo.LDSSize;
2050b57cec5SDimitry Andric HSACodeProps.mPrivateSegmentFixedSize = ProgramInfo.ScratchSize;
2068bcb0991SDimitry Andric HSACodeProps.mKernargSegmentAlign =
2078bcb0991SDimitry Andric std::max(MaxKernArgAlign, Align(4)).value();
2080b57cec5SDimitry Andric HSACodeProps.mWavefrontSize = STM.getWavefrontSize();
2090b57cec5SDimitry Andric HSACodeProps.mNumSGPRs = ProgramInfo.NumSGPR;
2100b57cec5SDimitry Andric HSACodeProps.mNumVGPRs = ProgramInfo.NumVGPR;
2110b57cec5SDimitry Andric HSACodeProps.mMaxFlatWorkGroupSize = MFI.getMaxFlatWorkGroupSize();
2120b57cec5SDimitry Andric HSACodeProps.mIsDynamicCallStack = ProgramInfo.DynamicCallStack;
2130b57cec5SDimitry Andric HSACodeProps.mIsXNACKEnabled = STM.isXNACKEnabled();
2140b57cec5SDimitry Andric HSACodeProps.mNumSpilledSGPRs = MFI.getNumSpilledSGPRs();
2150b57cec5SDimitry Andric HSACodeProps.mNumSpilledVGPRs = MFI.getNumSpilledVGPRs();
2160b57cec5SDimitry Andric
2170b57cec5SDimitry Andric return HSACodeProps;
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric
2200b57cec5SDimitry Andric Kernel::DebugProps::Metadata
getHSADebugProps(const MachineFunction & MF,const SIProgramInfo & ProgramInfo) const2210b57cec5SDimitry Andric MetadataStreamerV2::getHSADebugProps(const MachineFunction &MF,
2220b57cec5SDimitry Andric const SIProgramInfo &ProgramInfo) const {
2230b57cec5SDimitry Andric return HSAMD::Kernel::DebugProps::Metadata();
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric
emitVersion()2260b57cec5SDimitry Andric void MetadataStreamerV2::emitVersion() {
2270b57cec5SDimitry Andric auto &Version = HSAMetadata.mVersion;
2280b57cec5SDimitry Andric
229*5f7ddb14SDimitry Andric Version.push_back(VersionMajorV2);
230*5f7ddb14SDimitry Andric Version.push_back(VersionMinorV2);
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric
emitPrintf(const Module & Mod)2330b57cec5SDimitry Andric void MetadataStreamerV2::emitPrintf(const Module &Mod) {
2340b57cec5SDimitry Andric auto &Printf = HSAMetadata.mPrintf;
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
2370b57cec5SDimitry Andric if (!Node)
2380b57cec5SDimitry Andric return;
2390b57cec5SDimitry Andric
2400b57cec5SDimitry Andric for (auto Op : Node->operands())
2410b57cec5SDimitry Andric if (Op->getNumOperands())
2425ffd83dbSDimitry Andric Printf.push_back(
2435ffd83dbSDimitry Andric std::string(cast<MDString>(Op->getOperand(0))->getString()));
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric
emitKernelLanguage(const Function & Func)2460b57cec5SDimitry Andric void MetadataStreamerV2::emitKernelLanguage(const Function &Func) {
2470b57cec5SDimitry Andric auto &Kernel = HSAMetadata.mKernels.back();
2480b57cec5SDimitry Andric
2490b57cec5SDimitry Andric // TODO: What about other languages?
2500b57cec5SDimitry Andric auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
2510b57cec5SDimitry Andric if (!Node || !Node->getNumOperands())
2520b57cec5SDimitry Andric return;
2530b57cec5SDimitry Andric auto Op0 = Node->getOperand(0);
2540b57cec5SDimitry Andric if (Op0->getNumOperands() <= 1)
2550b57cec5SDimitry Andric return;
2560b57cec5SDimitry Andric
2570b57cec5SDimitry Andric Kernel.mLanguage = "OpenCL C";
2580b57cec5SDimitry Andric Kernel.mLanguageVersion.push_back(
2590b57cec5SDimitry Andric mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue());
2600b57cec5SDimitry Andric Kernel.mLanguageVersion.push_back(
2610b57cec5SDimitry Andric mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue());
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric
emitKernelAttrs(const Function & Func)2640b57cec5SDimitry Andric void MetadataStreamerV2::emitKernelAttrs(const Function &Func) {
2650b57cec5SDimitry Andric auto &Attrs = HSAMetadata.mKernels.back().mAttrs;
2660b57cec5SDimitry Andric
2670b57cec5SDimitry Andric if (auto Node = Func.getMetadata("reqd_work_group_size"))
2680b57cec5SDimitry Andric Attrs.mReqdWorkGroupSize = getWorkGroupDimensions(Node);
2690b57cec5SDimitry Andric if (auto Node = Func.getMetadata("work_group_size_hint"))
2700b57cec5SDimitry Andric Attrs.mWorkGroupSizeHint = getWorkGroupDimensions(Node);
2710b57cec5SDimitry Andric if (auto Node = Func.getMetadata("vec_type_hint")) {
2720b57cec5SDimitry Andric Attrs.mVecTypeHint = getTypeName(
2730b57cec5SDimitry Andric cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
2740b57cec5SDimitry Andric mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue());
2750b57cec5SDimitry Andric }
2760b57cec5SDimitry Andric if (Func.hasFnAttribute("runtime-handle")) {
2770b57cec5SDimitry Andric Attrs.mRuntimeHandle =
2780b57cec5SDimitry Andric Func.getFnAttribute("runtime-handle").getValueAsString().str();
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric
emitKernelArgs(const Function & Func)2820b57cec5SDimitry Andric void MetadataStreamerV2::emitKernelArgs(const Function &Func) {
2830b57cec5SDimitry Andric for (auto &Arg : Func.args())
2840b57cec5SDimitry Andric emitKernelArg(Arg);
2850b57cec5SDimitry Andric
2860b57cec5SDimitry Andric emitHiddenKernelArgs(Func);
2870b57cec5SDimitry Andric }
2880b57cec5SDimitry Andric
emitKernelArg(const Argument & Arg)2890b57cec5SDimitry Andric void MetadataStreamerV2::emitKernelArg(const Argument &Arg) {
2900b57cec5SDimitry Andric auto Func = Arg.getParent();
2910b57cec5SDimitry Andric auto ArgNo = Arg.getArgNo();
2920b57cec5SDimitry Andric const MDNode *Node;
2930b57cec5SDimitry Andric
2940b57cec5SDimitry Andric StringRef Name;
2950b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_name");
2960b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
2970b57cec5SDimitry Andric Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
2980b57cec5SDimitry Andric else if (Arg.hasName())
2990b57cec5SDimitry Andric Name = Arg.getName();
3000b57cec5SDimitry Andric
3010b57cec5SDimitry Andric StringRef TypeName;
3020b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_type");
3030b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
3040b57cec5SDimitry Andric TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
3050b57cec5SDimitry Andric
3060b57cec5SDimitry Andric StringRef BaseTypeName;
3070b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_base_type");
3080b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
3090b57cec5SDimitry Andric BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
3100b57cec5SDimitry Andric
3110b57cec5SDimitry Andric StringRef AccQual;
3120b57cec5SDimitry Andric if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() &&
3130b57cec5SDimitry Andric Arg.hasNoAliasAttr()) {
3140b57cec5SDimitry Andric AccQual = "read_only";
3150b57cec5SDimitry Andric } else {
3160b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_access_qual");
3170b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
3180b57cec5SDimitry Andric AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
3190b57cec5SDimitry Andric }
3200b57cec5SDimitry Andric
3210b57cec5SDimitry Andric StringRef TypeQual;
3220b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_type_qual");
3230b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
3240b57cec5SDimitry Andric TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
3250b57cec5SDimitry Andric
3260b57cec5SDimitry Andric const DataLayout &DL = Func->getParent()->getDataLayout();
3270b57cec5SDimitry Andric
3285ffd83dbSDimitry Andric MaybeAlign PointeeAlign;
329af732203SDimitry Andric if (auto PtrTy = dyn_cast<PointerType>(Arg.getType())) {
3300b57cec5SDimitry Andric if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
331af732203SDimitry Andric // FIXME: Should report this for all address spaces
3325ffd83dbSDimitry Andric PointeeAlign = DL.getValueOrABITypeAlignment(Arg.getParamAlign(),
3335ffd83dbSDimitry Andric PtrTy->getElementType());
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric }
3360b57cec5SDimitry Andric
337af732203SDimitry Andric Type *ArgTy;
338af732203SDimitry Andric Align ArgAlign;
339af732203SDimitry Andric std::tie(ArgTy, ArgAlign) = getArgumentTypeAlign(Arg, DL);
340af732203SDimitry Andric
341af732203SDimitry Andric emitKernelArg(DL, ArgTy, ArgAlign,
342af732203SDimitry Andric getValueKind(ArgTy, TypeQual, BaseTypeName), PointeeAlign, Name,
343af732203SDimitry Andric TypeName, BaseTypeName, AccQual, TypeQual);
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric
emitKernelArg(const DataLayout & DL,Type * Ty,Align Alignment,ValueKind ValueKind,MaybeAlign PointeeAlign,StringRef Name,StringRef TypeName,StringRef BaseTypeName,StringRef AccQual,StringRef TypeQual)3460b57cec5SDimitry Andric void MetadataStreamerV2::emitKernelArg(const DataLayout &DL, Type *Ty,
347af732203SDimitry Andric Align Alignment, ValueKind ValueKind,
3485ffd83dbSDimitry Andric MaybeAlign PointeeAlign, StringRef Name,
3490b57cec5SDimitry Andric StringRef TypeName,
3500b57cec5SDimitry Andric StringRef BaseTypeName,
3510b57cec5SDimitry Andric StringRef AccQual, StringRef TypeQual) {
3520b57cec5SDimitry Andric HSAMetadata.mKernels.back().mArgs.push_back(Kernel::Arg::Metadata());
3530b57cec5SDimitry Andric auto &Arg = HSAMetadata.mKernels.back().mArgs.back();
3540b57cec5SDimitry Andric
3555ffd83dbSDimitry Andric Arg.mName = std::string(Name);
3565ffd83dbSDimitry Andric Arg.mTypeName = std::string(TypeName);
3570b57cec5SDimitry Andric Arg.mSize = DL.getTypeAllocSize(Ty);
358af732203SDimitry Andric Arg.mAlign = Alignment.value();
3590b57cec5SDimitry Andric Arg.mValueKind = ValueKind;
3605ffd83dbSDimitry Andric Arg.mPointeeAlign = PointeeAlign ? PointeeAlign->value() : 0;
3610b57cec5SDimitry Andric
3620b57cec5SDimitry Andric if (auto PtrTy = dyn_cast<PointerType>(Ty))
3630b57cec5SDimitry Andric Arg.mAddrSpaceQual = getAddressSpaceQualifier(PtrTy->getAddressSpace());
3640b57cec5SDimitry Andric
3650b57cec5SDimitry Andric Arg.mAccQual = getAccessQualifier(AccQual);
3660b57cec5SDimitry Andric
3670b57cec5SDimitry Andric // TODO: Emit Arg.mActualAccQual.
3680b57cec5SDimitry Andric
3690b57cec5SDimitry Andric SmallVector<StringRef, 1> SplitTypeQuals;
3700b57cec5SDimitry Andric TypeQual.split(SplitTypeQuals, " ", -1, false);
3710b57cec5SDimitry Andric for (StringRef Key : SplitTypeQuals) {
3720b57cec5SDimitry Andric auto P = StringSwitch<bool*>(Key)
3730b57cec5SDimitry Andric .Case("const", &Arg.mIsConst)
3740b57cec5SDimitry Andric .Case("restrict", &Arg.mIsRestrict)
3750b57cec5SDimitry Andric .Case("volatile", &Arg.mIsVolatile)
3760b57cec5SDimitry Andric .Case("pipe", &Arg.mIsPipe)
3770b57cec5SDimitry Andric .Default(nullptr);
3780b57cec5SDimitry Andric if (P)
3790b57cec5SDimitry Andric *P = true;
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric
emitHiddenKernelArgs(const Function & Func)3830b57cec5SDimitry Andric void MetadataStreamerV2::emitHiddenKernelArgs(const Function &Func) {
3840b57cec5SDimitry Andric int HiddenArgNumBytes =
3850b57cec5SDimitry Andric getIntegerAttribute(Func, "amdgpu-implicitarg-num-bytes", 0);
3860b57cec5SDimitry Andric
3870b57cec5SDimitry Andric if (!HiddenArgNumBytes)
3880b57cec5SDimitry Andric return;
3890b57cec5SDimitry Andric
3900b57cec5SDimitry Andric auto &DL = Func.getParent()->getDataLayout();
3910b57cec5SDimitry Andric auto Int64Ty = Type::getInt64Ty(Func.getContext());
3920b57cec5SDimitry Andric
3930b57cec5SDimitry Andric if (HiddenArgNumBytes >= 8)
394af732203SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), ValueKind::HiddenGlobalOffsetX);
3950b57cec5SDimitry Andric if (HiddenArgNumBytes >= 16)
396af732203SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), ValueKind::HiddenGlobalOffsetY);
3970b57cec5SDimitry Andric if (HiddenArgNumBytes >= 24)
398af732203SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), ValueKind::HiddenGlobalOffsetZ);
3990b57cec5SDimitry Andric
4000b57cec5SDimitry Andric auto Int8PtrTy = Type::getInt8PtrTy(Func.getContext(),
4010b57cec5SDimitry Andric AMDGPUAS::GLOBAL_ADDRESS);
4020b57cec5SDimitry Andric
4030b57cec5SDimitry Andric // Emit "printf buffer" argument if printf is used, otherwise emit dummy
4040b57cec5SDimitry Andric // "none" argument.
4050b57cec5SDimitry Andric if (HiddenArgNumBytes >= 32) {
4060b57cec5SDimitry Andric if (Func.getParent()->getNamedMetadata("llvm.printf.fmts"))
407af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenPrintfBuffer);
408480093f4SDimitry Andric else if (Func.getParent()->getFunction("__ockl_hostcall_internal")) {
409480093f4SDimitry Andric // The printf runtime binding pass should have ensured that hostcall and
410480093f4SDimitry Andric // printf are not used in the same module.
411480093f4SDimitry Andric assert(!Func.getParent()->getNamedMetadata("llvm.printf.fmts"));
412af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenHostcallBuffer);
413480093f4SDimitry Andric } else
414af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenNone);
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric
4170b57cec5SDimitry Andric // Emit "default queue" and "completion action" arguments if enqueue kernel is
4180b57cec5SDimitry Andric // used, otherwise emit dummy "none" arguments.
4190b57cec5SDimitry Andric if (HiddenArgNumBytes >= 48) {
4200b57cec5SDimitry Andric if (Func.hasFnAttribute("calls-enqueue-kernel")) {
421af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenDefaultQueue);
422af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenCompletionAction);
4230b57cec5SDimitry Andric } else {
424af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenNone);
425af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenNone);
4260b57cec5SDimitry Andric }
4270b57cec5SDimitry Andric }
4280b57cec5SDimitry Andric
4290b57cec5SDimitry Andric // Emit the pointer argument for multi-grid object.
4300b57cec5SDimitry Andric if (HiddenArgNumBytes >= 56)
431af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), ValueKind::HiddenMultiGridSyncArg);
4320b57cec5SDimitry Andric }
4330b57cec5SDimitry Andric
emitTo(AMDGPUTargetStreamer & TargetStreamer)4340b57cec5SDimitry Andric bool MetadataStreamerV2::emitTo(AMDGPUTargetStreamer &TargetStreamer) {
4350b57cec5SDimitry Andric return TargetStreamer.EmitHSAMetadata(getHSAMetadata());
4360b57cec5SDimitry Andric }
4370b57cec5SDimitry Andric
begin(const Module & Mod,const IsaInfo::AMDGPUTargetID & TargetID)438*5f7ddb14SDimitry Andric void MetadataStreamerV2::begin(const Module &Mod,
439*5f7ddb14SDimitry Andric const IsaInfo::AMDGPUTargetID &TargetID) {
4400b57cec5SDimitry Andric emitVersion();
4410b57cec5SDimitry Andric emitPrintf(Mod);
4420b57cec5SDimitry Andric }
4430b57cec5SDimitry Andric
end()4440b57cec5SDimitry Andric void MetadataStreamerV2::end() {
4450b57cec5SDimitry Andric std::string HSAMetadataString;
4460b57cec5SDimitry Andric if (toString(HSAMetadata, HSAMetadataString))
4470b57cec5SDimitry Andric return;
4480b57cec5SDimitry Andric
4490b57cec5SDimitry Andric if (DumpHSAMetadata)
4500b57cec5SDimitry Andric dump(HSAMetadataString);
4510b57cec5SDimitry Andric if (VerifyHSAMetadata)
4520b57cec5SDimitry Andric verify(HSAMetadataString);
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric
emitKernel(const MachineFunction & MF,const SIProgramInfo & ProgramInfo)4550b57cec5SDimitry Andric void MetadataStreamerV2::emitKernel(const MachineFunction &MF,
4560b57cec5SDimitry Andric const SIProgramInfo &ProgramInfo) {
4570b57cec5SDimitry Andric auto &Func = MF.getFunction();
4580b57cec5SDimitry Andric if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL)
4590b57cec5SDimitry Andric return;
4600b57cec5SDimitry Andric
4610b57cec5SDimitry Andric auto CodeProps = getHSACodeProps(MF, ProgramInfo);
4620b57cec5SDimitry Andric auto DebugProps = getHSADebugProps(MF, ProgramInfo);
4630b57cec5SDimitry Andric
4640b57cec5SDimitry Andric HSAMetadata.mKernels.push_back(Kernel::Metadata());
4650b57cec5SDimitry Andric auto &Kernel = HSAMetadata.mKernels.back();
4660b57cec5SDimitry Andric
4675ffd83dbSDimitry Andric Kernel.mName = std::string(Func.getName());
4680b57cec5SDimitry Andric Kernel.mSymbolName = (Twine(Func.getName()) + Twine("@kd")).str();
4690b57cec5SDimitry Andric emitKernelLanguage(Func);
4700b57cec5SDimitry Andric emitKernelAttrs(Func);
4710b57cec5SDimitry Andric emitKernelArgs(Func);
4720b57cec5SDimitry Andric HSAMetadata.mKernels.back().mCodeProps = CodeProps;
4730b57cec5SDimitry Andric HSAMetadata.mKernels.back().mDebugProps = DebugProps;
4740b57cec5SDimitry Andric }
4750b57cec5SDimitry Andric
4760b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4770b57cec5SDimitry Andric // HSAMetadataStreamerV3
4780b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4790b57cec5SDimitry Andric
dump(StringRef HSAMetadataString) const4800b57cec5SDimitry Andric void MetadataStreamerV3::dump(StringRef HSAMetadataString) const {
4810b57cec5SDimitry Andric errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
4820b57cec5SDimitry Andric }
4830b57cec5SDimitry Andric
verify(StringRef HSAMetadataString) const4840b57cec5SDimitry Andric void MetadataStreamerV3::verify(StringRef HSAMetadataString) const {
4850b57cec5SDimitry Andric errs() << "AMDGPU HSA Metadata Parser Test: ";
4860b57cec5SDimitry Andric
4870b57cec5SDimitry Andric msgpack::Document FromHSAMetadataString;
4880b57cec5SDimitry Andric
4890b57cec5SDimitry Andric if (!FromHSAMetadataString.fromYAML(HSAMetadataString)) {
4900b57cec5SDimitry Andric errs() << "FAIL\n";
4910b57cec5SDimitry Andric return;
4920b57cec5SDimitry Andric }
4930b57cec5SDimitry Andric
4940b57cec5SDimitry Andric std::string ToHSAMetadataString;
4950b57cec5SDimitry Andric raw_string_ostream StrOS(ToHSAMetadataString);
4960b57cec5SDimitry Andric FromHSAMetadataString.toYAML(StrOS);
4970b57cec5SDimitry Andric
4980b57cec5SDimitry Andric errs() << (HSAMetadataString == StrOS.str() ? "PASS" : "FAIL") << '\n';
4990b57cec5SDimitry Andric if (HSAMetadataString != ToHSAMetadataString) {
5000b57cec5SDimitry Andric errs() << "Original input: " << HSAMetadataString << '\n'
5010b57cec5SDimitry Andric << "Produced output: " << StrOS.str() << '\n';
5020b57cec5SDimitry Andric }
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric
5050b57cec5SDimitry Andric Optional<StringRef>
getAccessQualifier(StringRef AccQual) const5060b57cec5SDimitry Andric MetadataStreamerV3::getAccessQualifier(StringRef AccQual) const {
5070b57cec5SDimitry Andric return StringSwitch<Optional<StringRef>>(AccQual)
5080b57cec5SDimitry Andric .Case("read_only", StringRef("read_only"))
5090b57cec5SDimitry Andric .Case("write_only", StringRef("write_only"))
5100b57cec5SDimitry Andric .Case("read_write", StringRef("read_write"))
5110b57cec5SDimitry Andric .Default(None);
5120b57cec5SDimitry Andric }
5130b57cec5SDimitry Andric
5140b57cec5SDimitry Andric Optional<StringRef>
getAddressSpaceQualifier(unsigned AddressSpace) const5150b57cec5SDimitry Andric MetadataStreamerV3::getAddressSpaceQualifier(unsigned AddressSpace) const {
5160b57cec5SDimitry Andric switch (AddressSpace) {
5170b57cec5SDimitry Andric case AMDGPUAS::PRIVATE_ADDRESS:
5180b57cec5SDimitry Andric return StringRef("private");
5190b57cec5SDimitry Andric case AMDGPUAS::GLOBAL_ADDRESS:
5200b57cec5SDimitry Andric return StringRef("global");
5210b57cec5SDimitry Andric case AMDGPUAS::CONSTANT_ADDRESS:
5220b57cec5SDimitry Andric return StringRef("constant");
5230b57cec5SDimitry Andric case AMDGPUAS::LOCAL_ADDRESS:
5240b57cec5SDimitry Andric return StringRef("local");
5250b57cec5SDimitry Andric case AMDGPUAS::FLAT_ADDRESS:
5260b57cec5SDimitry Andric return StringRef("generic");
5270b57cec5SDimitry Andric case AMDGPUAS::REGION_ADDRESS:
5280b57cec5SDimitry Andric return StringRef("region");
5290b57cec5SDimitry Andric default:
5300b57cec5SDimitry Andric return None;
5310b57cec5SDimitry Andric }
5320b57cec5SDimitry Andric }
5330b57cec5SDimitry Andric
getValueKind(Type * Ty,StringRef TypeQual,StringRef BaseTypeName) const5340b57cec5SDimitry Andric StringRef MetadataStreamerV3::getValueKind(Type *Ty, StringRef TypeQual,
5350b57cec5SDimitry Andric StringRef BaseTypeName) const {
5360b57cec5SDimitry Andric if (TypeQual.find("pipe") != StringRef::npos)
5370b57cec5SDimitry Andric return "pipe";
5380b57cec5SDimitry Andric
5390b57cec5SDimitry Andric return StringSwitch<StringRef>(BaseTypeName)
5400b57cec5SDimitry Andric .Case("image1d_t", "image")
5410b57cec5SDimitry Andric .Case("image1d_array_t", "image")
5420b57cec5SDimitry Andric .Case("image1d_buffer_t", "image")
5430b57cec5SDimitry Andric .Case("image2d_t", "image")
5440b57cec5SDimitry Andric .Case("image2d_array_t", "image")
5450b57cec5SDimitry Andric .Case("image2d_array_depth_t", "image")
5460b57cec5SDimitry Andric .Case("image2d_array_msaa_t", "image")
5470b57cec5SDimitry Andric .Case("image2d_array_msaa_depth_t", "image")
5480b57cec5SDimitry Andric .Case("image2d_depth_t", "image")
5490b57cec5SDimitry Andric .Case("image2d_msaa_t", "image")
5500b57cec5SDimitry Andric .Case("image2d_msaa_depth_t", "image")
5510b57cec5SDimitry Andric .Case("image3d_t", "image")
5520b57cec5SDimitry Andric .Case("sampler_t", "sampler")
5530b57cec5SDimitry Andric .Case("queue_t", "queue")
5540b57cec5SDimitry Andric .Default(isa<PointerType>(Ty)
5550b57cec5SDimitry Andric ? (Ty->getPointerAddressSpace() == AMDGPUAS::LOCAL_ADDRESS
5560b57cec5SDimitry Andric ? "dynamic_shared_pointer"
5570b57cec5SDimitry Andric : "global_buffer")
5580b57cec5SDimitry Andric : "by_value");
5590b57cec5SDimitry Andric }
5600b57cec5SDimitry Andric
getTypeName(Type * Ty,bool Signed) const5610b57cec5SDimitry Andric std::string MetadataStreamerV3::getTypeName(Type *Ty, bool Signed) const {
5620b57cec5SDimitry Andric switch (Ty->getTypeID()) {
5630b57cec5SDimitry Andric case Type::IntegerTyID: {
5640b57cec5SDimitry Andric if (!Signed)
5650b57cec5SDimitry Andric return (Twine('u') + getTypeName(Ty, true)).str();
5660b57cec5SDimitry Andric
5670b57cec5SDimitry Andric auto BitWidth = Ty->getIntegerBitWidth();
5680b57cec5SDimitry Andric switch (BitWidth) {
5690b57cec5SDimitry Andric case 8:
5700b57cec5SDimitry Andric return "char";
5710b57cec5SDimitry Andric case 16:
5720b57cec5SDimitry Andric return "short";
5730b57cec5SDimitry Andric case 32:
5740b57cec5SDimitry Andric return "int";
5750b57cec5SDimitry Andric case 64:
5760b57cec5SDimitry Andric return "long";
5770b57cec5SDimitry Andric default:
5780b57cec5SDimitry Andric return (Twine('i') + Twine(BitWidth)).str();
5790b57cec5SDimitry Andric }
5800b57cec5SDimitry Andric }
5810b57cec5SDimitry Andric case Type::HalfTyID:
5820b57cec5SDimitry Andric return "half";
5830b57cec5SDimitry Andric case Type::FloatTyID:
5840b57cec5SDimitry Andric return "float";
5850b57cec5SDimitry Andric case Type::DoubleTyID:
5860b57cec5SDimitry Andric return "double";
5875ffd83dbSDimitry Andric case Type::FixedVectorTyID: {
5885ffd83dbSDimitry Andric auto VecTy = cast<FixedVectorType>(Ty);
5890b57cec5SDimitry Andric auto ElTy = VecTy->getElementType();
5905ffd83dbSDimitry Andric auto NumElements = VecTy->getNumElements();
5910b57cec5SDimitry Andric return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
5920b57cec5SDimitry Andric }
5930b57cec5SDimitry Andric default:
5940b57cec5SDimitry Andric return "unknown";
5950b57cec5SDimitry Andric }
5960b57cec5SDimitry Andric }
5970b57cec5SDimitry Andric
5980b57cec5SDimitry Andric msgpack::ArrayDocNode
getWorkGroupDimensions(MDNode * Node) const5990b57cec5SDimitry Andric MetadataStreamerV3::getWorkGroupDimensions(MDNode *Node) const {
6000b57cec5SDimitry Andric auto Dims = HSAMetadataDoc->getArrayNode();
6010b57cec5SDimitry Andric if (Node->getNumOperands() != 3)
6020b57cec5SDimitry Andric return Dims;
6030b57cec5SDimitry Andric
6040b57cec5SDimitry Andric for (auto &Op : Node->operands())
6050b57cec5SDimitry Andric Dims.push_back(Dims.getDocument()->getNode(
6060b57cec5SDimitry Andric uint64_t(mdconst::extract<ConstantInt>(Op)->getZExtValue())));
6070b57cec5SDimitry Andric return Dims;
6080b57cec5SDimitry Andric }
6090b57cec5SDimitry Andric
emitVersion()6100b57cec5SDimitry Andric void MetadataStreamerV3::emitVersion() {
6110b57cec5SDimitry Andric auto Version = HSAMetadataDoc->getArrayNode();
612*5f7ddb14SDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMajorV3));
613*5f7ddb14SDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMinorV3));
6140b57cec5SDimitry Andric getRootMetadata("amdhsa.version") = Version;
6150b57cec5SDimitry Andric }
6160b57cec5SDimitry Andric
emitPrintf(const Module & Mod)6170b57cec5SDimitry Andric void MetadataStreamerV3::emitPrintf(const Module &Mod) {
6180b57cec5SDimitry Andric auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
6190b57cec5SDimitry Andric if (!Node)
6200b57cec5SDimitry Andric return;
6210b57cec5SDimitry Andric
6220b57cec5SDimitry Andric auto Printf = HSAMetadataDoc->getArrayNode();
6230b57cec5SDimitry Andric for (auto Op : Node->operands())
6240b57cec5SDimitry Andric if (Op->getNumOperands())
6250b57cec5SDimitry Andric Printf.push_back(Printf.getDocument()->getNode(
6260b57cec5SDimitry Andric cast<MDString>(Op->getOperand(0))->getString(), /*Copy=*/true));
6270b57cec5SDimitry Andric getRootMetadata("amdhsa.printf") = Printf;
6280b57cec5SDimitry Andric }
6290b57cec5SDimitry Andric
emitKernelLanguage(const Function & Func,msgpack::MapDocNode Kern)6300b57cec5SDimitry Andric void MetadataStreamerV3::emitKernelLanguage(const Function &Func,
6310b57cec5SDimitry Andric msgpack::MapDocNode Kern) {
6320b57cec5SDimitry Andric // TODO: What about other languages?
6330b57cec5SDimitry Andric auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
6340b57cec5SDimitry Andric if (!Node || !Node->getNumOperands())
6350b57cec5SDimitry Andric return;
6360b57cec5SDimitry Andric auto Op0 = Node->getOperand(0);
6370b57cec5SDimitry Andric if (Op0->getNumOperands() <= 1)
6380b57cec5SDimitry Andric return;
6390b57cec5SDimitry Andric
6400b57cec5SDimitry Andric Kern[".language"] = Kern.getDocument()->getNode("OpenCL C");
6410b57cec5SDimitry Andric auto LanguageVersion = Kern.getDocument()->getArrayNode();
6420b57cec5SDimitry Andric LanguageVersion.push_back(Kern.getDocument()->getNode(
6430b57cec5SDimitry Andric mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue()));
6440b57cec5SDimitry Andric LanguageVersion.push_back(Kern.getDocument()->getNode(
6450b57cec5SDimitry Andric mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue()));
6460b57cec5SDimitry Andric Kern[".language_version"] = LanguageVersion;
6470b57cec5SDimitry Andric }
6480b57cec5SDimitry Andric
emitKernelAttrs(const Function & Func,msgpack::MapDocNode Kern)6490b57cec5SDimitry Andric void MetadataStreamerV3::emitKernelAttrs(const Function &Func,
6500b57cec5SDimitry Andric msgpack::MapDocNode Kern) {
6510b57cec5SDimitry Andric
6520b57cec5SDimitry Andric if (auto Node = Func.getMetadata("reqd_work_group_size"))
6530b57cec5SDimitry Andric Kern[".reqd_workgroup_size"] = getWorkGroupDimensions(Node);
6540b57cec5SDimitry Andric if (auto Node = Func.getMetadata("work_group_size_hint"))
6550b57cec5SDimitry Andric Kern[".workgroup_size_hint"] = getWorkGroupDimensions(Node);
6560b57cec5SDimitry Andric if (auto Node = Func.getMetadata("vec_type_hint")) {
6570b57cec5SDimitry Andric Kern[".vec_type_hint"] = Kern.getDocument()->getNode(
6580b57cec5SDimitry Andric getTypeName(
6590b57cec5SDimitry Andric cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
6600b57cec5SDimitry Andric mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue()),
6610b57cec5SDimitry Andric /*Copy=*/true);
6620b57cec5SDimitry Andric }
6630b57cec5SDimitry Andric if (Func.hasFnAttribute("runtime-handle")) {
6640b57cec5SDimitry Andric Kern[".device_enqueue_symbol"] = Kern.getDocument()->getNode(
6650b57cec5SDimitry Andric Func.getFnAttribute("runtime-handle").getValueAsString().str(),
6660b57cec5SDimitry Andric /*Copy=*/true);
6670b57cec5SDimitry Andric }
6680b57cec5SDimitry Andric }
6690b57cec5SDimitry Andric
emitKernelArgs(const Function & Func,msgpack::MapDocNode Kern)6700b57cec5SDimitry Andric void MetadataStreamerV3::emitKernelArgs(const Function &Func,
6710b57cec5SDimitry Andric msgpack::MapDocNode Kern) {
6720b57cec5SDimitry Andric unsigned Offset = 0;
6730b57cec5SDimitry Andric auto Args = HSAMetadataDoc->getArrayNode();
6740b57cec5SDimitry Andric for (auto &Arg : Func.args())
6750b57cec5SDimitry Andric emitKernelArg(Arg, Offset, Args);
6760b57cec5SDimitry Andric
6770b57cec5SDimitry Andric emitHiddenKernelArgs(Func, Offset, Args);
6780b57cec5SDimitry Andric
6790b57cec5SDimitry Andric Kern[".args"] = Args;
6800b57cec5SDimitry Andric }
6810b57cec5SDimitry Andric
emitKernelArg(const Argument & Arg,unsigned & Offset,msgpack::ArrayDocNode Args)6820b57cec5SDimitry Andric void MetadataStreamerV3::emitKernelArg(const Argument &Arg, unsigned &Offset,
6830b57cec5SDimitry Andric msgpack::ArrayDocNode Args) {
6840b57cec5SDimitry Andric auto Func = Arg.getParent();
6850b57cec5SDimitry Andric auto ArgNo = Arg.getArgNo();
6860b57cec5SDimitry Andric const MDNode *Node;
6870b57cec5SDimitry Andric
6880b57cec5SDimitry Andric StringRef Name;
6890b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_name");
6900b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
6910b57cec5SDimitry Andric Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
6920b57cec5SDimitry Andric else if (Arg.hasName())
6930b57cec5SDimitry Andric Name = Arg.getName();
6940b57cec5SDimitry Andric
6950b57cec5SDimitry Andric StringRef TypeName;
6960b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_type");
6970b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
6980b57cec5SDimitry Andric TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
6990b57cec5SDimitry Andric
7000b57cec5SDimitry Andric StringRef BaseTypeName;
7010b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_base_type");
7020b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
7030b57cec5SDimitry Andric BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
7040b57cec5SDimitry Andric
7050b57cec5SDimitry Andric StringRef AccQual;
7060b57cec5SDimitry Andric if (Arg.getType()->isPointerTy() && Arg.onlyReadsMemory() &&
7070b57cec5SDimitry Andric Arg.hasNoAliasAttr()) {
7080b57cec5SDimitry Andric AccQual = "read_only";
7090b57cec5SDimitry Andric } else {
7100b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_access_qual");
7110b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
7120b57cec5SDimitry Andric AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
7130b57cec5SDimitry Andric }
7140b57cec5SDimitry Andric
7150b57cec5SDimitry Andric StringRef TypeQual;
7160b57cec5SDimitry Andric Node = Func->getMetadata("kernel_arg_type_qual");
7170b57cec5SDimitry Andric if (Node && ArgNo < Node->getNumOperands())
7180b57cec5SDimitry Andric TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
7190b57cec5SDimitry Andric
7200b57cec5SDimitry Andric const DataLayout &DL = Func->getParent()->getDataLayout();
7210b57cec5SDimitry Andric
7225ffd83dbSDimitry Andric MaybeAlign PointeeAlign;
723af732203SDimitry Andric Type *Ty = Arg.hasByRefAttr() ? Arg.getParamByRefType() : Arg.getType();
724af732203SDimitry Andric
725af732203SDimitry Andric // FIXME: Need to distinguish in memory alignment from pointer alignment.
7260b57cec5SDimitry Andric if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
7270b57cec5SDimitry Andric if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
7285ffd83dbSDimitry Andric PointeeAlign = DL.getValueOrABITypeAlignment(Arg.getParamAlign(),
7295ffd83dbSDimitry Andric PtrTy->getElementType());
7300b57cec5SDimitry Andric }
7310b57cec5SDimitry Andric }
7320b57cec5SDimitry Andric
733af732203SDimitry Andric // There's no distinction between byval aggregates and raw aggregates.
734af732203SDimitry Andric Type *ArgTy;
735af732203SDimitry Andric Align ArgAlign;
736af732203SDimitry Andric std::tie(ArgTy, ArgAlign) = getArgumentTypeAlign(Arg, DL);
737af732203SDimitry Andric
738af732203SDimitry Andric emitKernelArg(DL, ArgTy, ArgAlign,
739af732203SDimitry Andric getValueKind(ArgTy, TypeQual, BaseTypeName), Offset, Args,
740af732203SDimitry Andric PointeeAlign, Name, TypeName, BaseTypeName, AccQual, TypeQual);
7410b57cec5SDimitry Andric }
7420b57cec5SDimitry Andric
emitKernelArg(const DataLayout & DL,Type * Ty,Align Alignment,StringRef ValueKind,unsigned & Offset,msgpack::ArrayDocNode Args,MaybeAlign PointeeAlign,StringRef Name,StringRef TypeName,StringRef BaseTypeName,StringRef AccQual,StringRef TypeQual)743af732203SDimitry Andric void MetadataStreamerV3::emitKernelArg(
744af732203SDimitry Andric const DataLayout &DL, Type *Ty, Align Alignment, StringRef ValueKind,
745af732203SDimitry Andric unsigned &Offset, msgpack::ArrayDocNode Args, MaybeAlign PointeeAlign,
746af732203SDimitry Andric StringRef Name, StringRef TypeName, StringRef BaseTypeName,
7470b57cec5SDimitry Andric StringRef AccQual, StringRef TypeQual) {
7480b57cec5SDimitry Andric auto Arg = Args.getDocument()->getMapNode();
7490b57cec5SDimitry Andric
7500b57cec5SDimitry Andric if (!Name.empty())
7510b57cec5SDimitry Andric Arg[".name"] = Arg.getDocument()->getNode(Name, /*Copy=*/true);
7520b57cec5SDimitry Andric if (!TypeName.empty())
7530b57cec5SDimitry Andric Arg[".type_name"] = Arg.getDocument()->getNode(TypeName, /*Copy=*/true);
7540b57cec5SDimitry Andric auto Size = DL.getTypeAllocSize(Ty);
7550b57cec5SDimitry Andric Arg[".size"] = Arg.getDocument()->getNode(Size);
7565ffd83dbSDimitry Andric Offset = alignTo(Offset, Alignment);
7570b57cec5SDimitry Andric Arg[".offset"] = Arg.getDocument()->getNode(Offset);
7580b57cec5SDimitry Andric Offset += Size;
7590b57cec5SDimitry Andric Arg[".value_kind"] = Arg.getDocument()->getNode(ValueKind, /*Copy=*/true);
7600b57cec5SDimitry Andric if (PointeeAlign)
7615ffd83dbSDimitry Andric Arg[".pointee_align"] = Arg.getDocument()->getNode(PointeeAlign->value());
7620b57cec5SDimitry Andric
7630b57cec5SDimitry Andric if (auto PtrTy = dyn_cast<PointerType>(Ty))
7640b57cec5SDimitry Andric if (auto Qualifier = getAddressSpaceQualifier(PtrTy->getAddressSpace()))
7650b57cec5SDimitry Andric Arg[".address_space"] = Arg.getDocument()->getNode(*Qualifier, /*Copy=*/true);
7660b57cec5SDimitry Andric
7670b57cec5SDimitry Andric if (auto AQ = getAccessQualifier(AccQual))
7680b57cec5SDimitry Andric Arg[".access"] = Arg.getDocument()->getNode(*AQ, /*Copy=*/true);
7690b57cec5SDimitry Andric
7700b57cec5SDimitry Andric // TODO: Emit Arg[".actual_access"].
7710b57cec5SDimitry Andric
7720b57cec5SDimitry Andric SmallVector<StringRef, 1> SplitTypeQuals;
7730b57cec5SDimitry Andric TypeQual.split(SplitTypeQuals, " ", -1, false);
7740b57cec5SDimitry Andric for (StringRef Key : SplitTypeQuals) {
7750b57cec5SDimitry Andric if (Key == "const")
7760b57cec5SDimitry Andric Arg[".is_const"] = Arg.getDocument()->getNode(true);
7770b57cec5SDimitry Andric else if (Key == "restrict")
7780b57cec5SDimitry Andric Arg[".is_restrict"] = Arg.getDocument()->getNode(true);
7790b57cec5SDimitry Andric else if (Key == "volatile")
7800b57cec5SDimitry Andric Arg[".is_volatile"] = Arg.getDocument()->getNode(true);
7810b57cec5SDimitry Andric else if (Key == "pipe")
7820b57cec5SDimitry Andric Arg[".is_pipe"] = Arg.getDocument()->getNode(true);
7830b57cec5SDimitry Andric }
7840b57cec5SDimitry Andric
7850b57cec5SDimitry Andric Args.push_back(Arg);
7860b57cec5SDimitry Andric }
7870b57cec5SDimitry Andric
emitHiddenKernelArgs(const Function & Func,unsigned & Offset,msgpack::ArrayDocNode Args)7880b57cec5SDimitry Andric void MetadataStreamerV3::emitHiddenKernelArgs(const Function &Func,
7890b57cec5SDimitry Andric unsigned &Offset,
7900b57cec5SDimitry Andric msgpack::ArrayDocNode Args) {
7910b57cec5SDimitry Andric int HiddenArgNumBytes =
7920b57cec5SDimitry Andric getIntegerAttribute(Func, "amdgpu-implicitarg-num-bytes", 0);
7930b57cec5SDimitry Andric
7940b57cec5SDimitry Andric if (!HiddenArgNumBytes)
7950b57cec5SDimitry Andric return;
7960b57cec5SDimitry Andric
7970b57cec5SDimitry Andric auto &DL = Func.getParent()->getDataLayout();
7980b57cec5SDimitry Andric auto Int64Ty = Type::getInt64Ty(Func.getContext());
7990b57cec5SDimitry Andric
8000b57cec5SDimitry Andric if (HiddenArgNumBytes >= 8)
801af732203SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset,
802af732203SDimitry Andric Args);
8030b57cec5SDimitry Andric if (HiddenArgNumBytes >= 16)
804af732203SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset,
805af732203SDimitry Andric Args);
8060b57cec5SDimitry Andric if (HiddenArgNumBytes >= 24)
807af732203SDimitry Andric emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset,
808af732203SDimitry Andric Args);
8090b57cec5SDimitry Andric
8100b57cec5SDimitry Andric auto Int8PtrTy =
8110b57cec5SDimitry Andric Type::getInt8PtrTy(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
8120b57cec5SDimitry Andric
8130b57cec5SDimitry Andric // Emit "printf buffer" argument if printf is used, otherwise emit dummy
8140b57cec5SDimitry Andric // "none" argument.
8150b57cec5SDimitry Andric if (HiddenArgNumBytes >= 32) {
8160b57cec5SDimitry Andric if (Func.getParent()->getNamedMetadata("llvm.printf.fmts"))
817af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset,
818af732203SDimitry Andric Args);
819480093f4SDimitry Andric else if (Func.getParent()->getFunction("__ockl_hostcall_internal")) {
820480093f4SDimitry Andric // The printf runtime binding pass should have ensured that hostcall and
821480093f4SDimitry Andric // printf are not used in the same module.
822480093f4SDimitry Andric assert(!Func.getParent()->getNamedMetadata("llvm.printf.fmts"));
823af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset,
824af732203SDimitry Andric Args);
825480093f4SDimitry Andric } else
826af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
8270b57cec5SDimitry Andric }
8280b57cec5SDimitry Andric
8290b57cec5SDimitry Andric // Emit "default queue" and "completion action" arguments if enqueue kernel is
8300b57cec5SDimitry Andric // used, otherwise emit dummy "none" arguments.
8310b57cec5SDimitry Andric if (HiddenArgNumBytes >= 48) {
8320b57cec5SDimitry Andric if (Func.hasFnAttribute("calls-enqueue-kernel")) {
833af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset,
834af732203SDimitry Andric Args);
835af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset,
836af732203SDimitry Andric Args);
8370b57cec5SDimitry Andric } else {
838af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
839af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
8400b57cec5SDimitry Andric }
8410b57cec5SDimitry Andric }
8420b57cec5SDimitry Andric
8430b57cec5SDimitry Andric // Emit the pointer argument for multi-grid object.
8440b57cec5SDimitry Andric if (HiddenArgNumBytes >= 56)
845af732203SDimitry Andric emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset,
846af732203SDimitry Andric Args);
8470b57cec5SDimitry Andric }
8480b57cec5SDimitry Andric
8490b57cec5SDimitry Andric msgpack::MapDocNode
getHSAKernelProps(const MachineFunction & MF,const SIProgramInfo & ProgramInfo) const8500b57cec5SDimitry Andric MetadataStreamerV3::getHSAKernelProps(const MachineFunction &MF,
8510b57cec5SDimitry Andric const SIProgramInfo &ProgramInfo) const {
8520b57cec5SDimitry Andric const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
8530b57cec5SDimitry Andric const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
8540b57cec5SDimitry Andric const Function &F = MF.getFunction();
8550b57cec5SDimitry Andric
8560b57cec5SDimitry Andric auto Kern = HSAMetadataDoc->getMapNode();
8570b57cec5SDimitry Andric
8588bcb0991SDimitry Andric Align MaxKernArgAlign;
8590b57cec5SDimitry Andric Kern[".kernarg_segment_size"] = Kern.getDocument()->getNode(
8600b57cec5SDimitry Andric STM.getKernArgSegmentSize(F, MaxKernArgAlign));
8610b57cec5SDimitry Andric Kern[".group_segment_fixed_size"] =
8620b57cec5SDimitry Andric Kern.getDocument()->getNode(ProgramInfo.LDSSize);
8630b57cec5SDimitry Andric Kern[".private_segment_fixed_size"] =
8640b57cec5SDimitry Andric Kern.getDocument()->getNode(ProgramInfo.ScratchSize);
8650b57cec5SDimitry Andric Kern[".kernarg_segment_align"] =
8668bcb0991SDimitry Andric Kern.getDocument()->getNode(std::max(Align(4), MaxKernArgAlign).value());
8670b57cec5SDimitry Andric Kern[".wavefront_size"] =
8680b57cec5SDimitry Andric Kern.getDocument()->getNode(STM.getWavefrontSize());
8690b57cec5SDimitry Andric Kern[".sgpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumSGPR);
8700b57cec5SDimitry Andric Kern[".vgpr_count"] = Kern.getDocument()->getNode(ProgramInfo.NumVGPR);
8710b57cec5SDimitry Andric Kern[".max_flat_workgroup_size"] =
8720b57cec5SDimitry Andric Kern.getDocument()->getNode(MFI.getMaxFlatWorkGroupSize());
8730b57cec5SDimitry Andric Kern[".sgpr_spill_count"] =
8740b57cec5SDimitry Andric Kern.getDocument()->getNode(MFI.getNumSpilledSGPRs());
8750b57cec5SDimitry Andric Kern[".vgpr_spill_count"] =
8760b57cec5SDimitry Andric Kern.getDocument()->getNode(MFI.getNumSpilledVGPRs());
8770b57cec5SDimitry Andric
8780b57cec5SDimitry Andric return Kern;
8790b57cec5SDimitry Andric }
8800b57cec5SDimitry Andric
emitTo(AMDGPUTargetStreamer & TargetStreamer)8810b57cec5SDimitry Andric bool MetadataStreamerV3::emitTo(AMDGPUTargetStreamer &TargetStreamer) {
8820b57cec5SDimitry Andric return TargetStreamer.EmitHSAMetadata(*HSAMetadataDoc, true);
8830b57cec5SDimitry Andric }
8840b57cec5SDimitry Andric
begin(const Module & Mod,const IsaInfo::AMDGPUTargetID & TargetID)885*5f7ddb14SDimitry Andric void MetadataStreamerV3::begin(const Module &Mod,
886*5f7ddb14SDimitry Andric const IsaInfo::AMDGPUTargetID &TargetID) {
8870b57cec5SDimitry Andric emitVersion();
8880b57cec5SDimitry Andric emitPrintf(Mod);
8890b57cec5SDimitry Andric getRootMetadata("amdhsa.kernels") = HSAMetadataDoc->getArrayNode();
8900b57cec5SDimitry Andric }
8910b57cec5SDimitry Andric
end()8920b57cec5SDimitry Andric void MetadataStreamerV3::end() {
8930b57cec5SDimitry Andric std::string HSAMetadataString;
8940b57cec5SDimitry Andric raw_string_ostream StrOS(HSAMetadataString);
8950b57cec5SDimitry Andric HSAMetadataDoc->toYAML(StrOS);
8960b57cec5SDimitry Andric
8970b57cec5SDimitry Andric if (DumpHSAMetadata)
8980b57cec5SDimitry Andric dump(StrOS.str());
8990b57cec5SDimitry Andric if (VerifyHSAMetadata)
9000b57cec5SDimitry Andric verify(StrOS.str());
9010b57cec5SDimitry Andric }
9020b57cec5SDimitry Andric
emitKernel(const MachineFunction & MF,const SIProgramInfo & ProgramInfo)9030b57cec5SDimitry Andric void MetadataStreamerV3::emitKernel(const MachineFunction &MF,
9040b57cec5SDimitry Andric const SIProgramInfo &ProgramInfo) {
9050b57cec5SDimitry Andric auto &Func = MF.getFunction();
9060b57cec5SDimitry Andric auto Kern = getHSAKernelProps(MF, ProgramInfo);
9070b57cec5SDimitry Andric
9080b57cec5SDimitry Andric assert(Func.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
9090b57cec5SDimitry Andric Func.getCallingConv() == CallingConv::SPIR_KERNEL);
9100b57cec5SDimitry Andric
9110b57cec5SDimitry Andric auto Kernels =
9120b57cec5SDimitry Andric getRootMetadata("amdhsa.kernels").getArray(/*Convert=*/true);
9130b57cec5SDimitry Andric
9140b57cec5SDimitry Andric {
9150b57cec5SDimitry Andric Kern[".name"] = Kern.getDocument()->getNode(Func.getName());
9160b57cec5SDimitry Andric Kern[".symbol"] = Kern.getDocument()->getNode(
9170b57cec5SDimitry Andric (Twine(Func.getName()) + Twine(".kd")).str(), /*Copy=*/true);
9180b57cec5SDimitry Andric emitKernelLanguage(Func, Kern);
9190b57cec5SDimitry Andric emitKernelAttrs(Func, Kern);
9200b57cec5SDimitry Andric emitKernelArgs(Func, Kern);
9210b57cec5SDimitry Andric }
9220b57cec5SDimitry Andric
9230b57cec5SDimitry Andric Kernels.push_back(Kern);
9240b57cec5SDimitry Andric }
9250b57cec5SDimitry Andric
926*5f7ddb14SDimitry Andric //===----------------------------------------------------------------------===//
927*5f7ddb14SDimitry Andric // HSAMetadataStreamerV4
928*5f7ddb14SDimitry Andric //===----------------------------------------------------------------------===//
929*5f7ddb14SDimitry Andric
emitVersion()930*5f7ddb14SDimitry Andric void MetadataStreamerV4::emitVersion() {
931*5f7ddb14SDimitry Andric auto Version = HSAMetadataDoc->getArrayNode();
932*5f7ddb14SDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMajorV4));
933*5f7ddb14SDimitry Andric Version.push_back(Version.getDocument()->getNode(VersionMinorV4));
934*5f7ddb14SDimitry Andric getRootMetadata("amdhsa.version") = Version;
935*5f7ddb14SDimitry Andric }
936*5f7ddb14SDimitry Andric
emitTargetID(const IsaInfo::AMDGPUTargetID & TargetID)937*5f7ddb14SDimitry Andric void MetadataStreamerV4::emitTargetID(const IsaInfo::AMDGPUTargetID &TargetID) {
938*5f7ddb14SDimitry Andric getRootMetadata("amdhsa.target") =
939*5f7ddb14SDimitry Andric HSAMetadataDoc->getNode(TargetID.toString(), /*Copy=*/true);
940*5f7ddb14SDimitry Andric }
941*5f7ddb14SDimitry Andric
begin(const Module & Mod,const IsaInfo::AMDGPUTargetID & TargetID)942*5f7ddb14SDimitry Andric void MetadataStreamerV4::begin(const Module &Mod,
943*5f7ddb14SDimitry Andric const IsaInfo::AMDGPUTargetID &TargetID) {
944*5f7ddb14SDimitry Andric emitVersion();
945*5f7ddb14SDimitry Andric emitTargetID(TargetID);
946*5f7ddb14SDimitry Andric emitPrintf(Mod);
947*5f7ddb14SDimitry Andric getRootMetadata("amdhsa.kernels") = HSAMetadataDoc->getArrayNode();
948*5f7ddb14SDimitry Andric }
949*5f7ddb14SDimitry Andric
9500b57cec5SDimitry Andric } // end namespace HSAMD
9510b57cec5SDimitry Andric } // end namespace AMDGPU
9520b57cec5SDimitry Andric } // end namespace llvm
953