1 //===- SPIRVMDWalker.h - SPIR-V metadata walker header file ----*- C++ -*-===// 2 // 3 // The LLVM/SPIRV Translator 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 // 10 // Permission is hereby granted, free of charge, to any person obtaining a 11 // copy of this software and associated documentation files (the "Software"), 12 // to deal with the Software without restriction, including without limitation 13 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 // and/or sell copies of the Software, and to permit persons to whom the 15 // Software is furnished to do so, subject to the following conditions: 16 // 17 // Redistributions of source code must retain the above copyright notice, 18 // this list of conditions and the following disclaimers. 19 // Redistributions in binary form must reproduce the above copyright notice, 20 // this list of conditions and the following disclaimers in the documentation 21 // and/or other materials provided with the distribution. 22 // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 // contributors may be used to endorse or promote products derived from this 24 // Software without specific prior written permission. 25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 // THE SOFTWARE. 32 // 33 //===----------------------------------------------------------------------===// 34 /// \file 35 /// 36 /// This file declares classes for walking SPIR-V metadata. 37 /// 38 //===----------------------------------------------------------------------===// 39 40 #ifndef LIB_SPIRV_SPIRVMDWALKER_H_ 41 #define LIB_SPIRV_SPIRVMDWALKER_H_ 42 43 #include "llvm/IR/Metadata.h" 44 #include "SPIRVInternal.h" 45 46 #include <functional> 47 using namespace llvm; 48 49 namespace SPIRV { 50 51 class SPIRVMDWalker { 52 public: 53 template<typename ParentT> struct MDWrapper; 54 55 struct NamedMDWrapper { NamedMDWrapperNamedMDWrapper56 NamedMDWrapper(NamedMDNode *Named, SPIRVMDWalker& WW) 57 :NMD(Named), W(WW), I(0), Q(true){ 58 E = Named ? Named->getNumOperands() : 0; 59 } 60 61 operator bool() const { return NMD;} 62 atEndNamedMDWrapper63 bool atEnd() const { return !(NMD && I < E);} 64 nextOpNamedMDWrapper65 MDWrapper<NamedMDWrapper> nextOp() { 66 if (!Q) 67 assert(I < E && "out of bound"); 68 return MDWrapper<NamedMDWrapper>((NMD && I < E) ? NMD->getOperand(I++) 69 : nullptr, *this, W); 70 } 71 setQuietNamedMDWrapper72 NamedMDWrapper &setQuiet(bool Quiet) { 73 Q = Quiet; 74 return *this; 75 } 76 77 NamedMDNode *NMD; 78 SPIRVMDWalker &W; 79 unsigned I; 80 unsigned E; 81 bool Q; // Quiet 82 }; 83 84 template<typename ParentT> 85 struct MDWrapper { MDWrapperMDWrapper86 MDWrapper(MDNode *Node, ParentT &Parent, SPIRVMDWalker &Walker) 87 :M(Node), P(Parent), W(Walker), I(0), Q(false){ 88 E = Node ? Node->getNumOperands() : 0; 89 } 90 91 operator bool() const { return M;} 92 atEndMDWrapper93 bool atEnd() const { return !(M && I < E);} 94 95 template<typename T> getMDWrapper96 MDWrapper &get(T &V) { 97 if (!Q) 98 assert(I < E && "out of bound"); 99 if (atEnd()) 100 return *this; 101 V = mdconst::dyn_extract<ConstantInt>(M->getOperand(I++)) 102 ->getZExtValue(); 103 return *this; 104 } 105 getMDWrapper106 MDWrapper &get(std::string &S) { 107 if (!Q) 108 assert (I < E && "out of bound"); 109 if (atEnd()) 110 return *this; 111 Metadata* Op = M->getOperand(I++); 112 if (!Op) 113 S = ""; 114 else if (auto Str = dyn_cast<MDString>(Op)) 115 S = Str->getString().str(); 116 else 117 S = ""; 118 return *this; 119 } 120 getMDWrapper121 MDWrapper &get(Function *&F) { 122 if (!Q) 123 assert (I < E && "out of bound"); 124 if (atEnd()) 125 return *this; 126 F = mdconst::dyn_extract<Function>(M->getOperand(I++)); 127 return *this; 128 } 129 getMDWrapper130 MDWrapper &get(SmallVectorImpl<std::string> &SV) { 131 if (atEnd()) 132 return *this; 133 while (I < E) { 134 std::string S; 135 get(S); 136 SV.push_back(S); 137 } 138 return *this; 139 } 140 nextOpMDWrapper141 MDWrapper<MDWrapper> nextOp() { 142 if (!Q) 143 assert (I < E && "out of bound"); 144 return MDWrapper<MDWrapper>((M && I < E) ? 145 dyn_cast<MDNode>(M->getOperand(I++)) : nullptr, *this, W); 146 } 147 doneMDWrapper148 ParentT &done() { 149 return P; 150 } 151 setQuietMDWrapper152 MDWrapper &setQuiet(bool Quiet) { 153 Q = Quiet; 154 return *this; 155 } 156 157 MDNode *M; 158 ParentT &P; 159 SPIRVMDWalker &W; 160 SmallVector<Metadata *, 10> V; 161 unsigned I; 162 unsigned E; 163 bool Q; // Quiet 164 }; 165 SPIRVMDWalker(Module & Mod)166 explicit SPIRVMDWalker(Module &Mod):M(Mod), C(Mod.getContext()){} 167 getNamedMD(StringRef Name)168 NamedMDWrapper getNamedMD(StringRef Name) { 169 return NamedMDWrapper(M.getNamedMetadata(Name), *this); 170 } 171 172 friend struct NamedMDWrapper; 173 private: 174 Module& M; 175 LLVMContext& C; 176 }; 177 178 } /* namespace SPIRV */ 179 180 #endif /* LIB_SPIRV_SPIRVMDBUILDER_H_ */ 181