• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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