• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- SPIRVDecorate.h - SPIR-V Decorations ----------------------*- 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 defines SPIR-V decorations.
37 ///
38 //===----------------------------------------------------------------------===//
39 
40 #ifndef SPIRVDECORATE_HPP_
41 #define SPIRVDECORATE_HPP_
42 
43 #include "SPIRVEntry.h"
44 #include "SPIRVUtil.h"
45 #include "SPIRVStream.h"
46 #include <string>
47 #include <vector>
48 #include <utility>
49 
50 namespace SPIRV{
51 class SPIRVDecorationGroup;
52 class SPIRVDecorateGeneric:public SPIRVAnnotationGeneric{
53 public:
54   // Complete constructor for decorations without literals
55   SPIRVDecorateGeneric(Op OC, SPIRVWord WC, Decoration TheDec,
56       SPIRVEntry *TheTarget);
57   // Complete constructor for decorations with one word literal
58   SPIRVDecorateGeneric(Op OC, SPIRVWord WC, Decoration TheDec,
59       SPIRVEntry *TheTarget, SPIRVWord V);
60   // Incomplete constructor
61   SPIRVDecorateGeneric(Op OC);
62 
63   SPIRVWord getLiteral(size_t) const;
64   Decoration getDecorateKind() const;
65   size_t getLiteralCount() const;
66   /// Compare for kind and literal only.
67   struct Comparator {
68     bool operator()(const SPIRVDecorateGeneric *A, const SPIRVDecorateGeneric *B);
69   };
70   /// Compare kind, literals and target.
71   friend bool operator==(const SPIRVDecorateGeneric &A,
72       const SPIRVDecorateGeneric &B);
73 
getOwner()74   SPIRVDecorationGroup* getOwner() const {
75     return Owner;
76   }
77 
setOwner(SPIRVDecorationGroup * owner)78   void setOwner(SPIRVDecorationGroup* owner) {
79     Owner = owner;
80   }
81 
getRequiredCapability()82   SPIRVCapVec getRequiredCapability() const {
83     return getCapability(Dec);
84   }
85 
getRequiredSPIRVVersion()86   SPIRVWord getRequiredSPIRVVersion() const override {
87     switch (Dec) {
88     case DecorationSpecId:
89       if (getModule()->hasCapability(CapabilityKernel))
90         return SPIRV_1_1;
91       else
92         return SPIRV_1_0;
93 
94     case DecorationMaxByteOffset:
95       return SPIRV_1_1;
96 
97     default:
98       return SPIRV_1_0;
99     }
100   }
101 
102 protected:
103   Decoration Dec;
104   std::vector<SPIRVWord> Literals;
105   SPIRVDecorationGroup *Owner; // Owning decorate group
106 };
107 
108 class SPIRVDecorateSet: public std::multiset<const SPIRVDecorateGeneric *,
109     SPIRVDecorateGeneric::Comparator> {
110     public:
111   typedef std::multiset<const SPIRVDecorateGeneric *,
112       SPIRVDecorateGeneric::Comparator> BaseType;
insert(const value_type & Dec)113   iterator insert(const value_type& Dec) {
114     auto ER = BaseType::equal_range(Dec);
115     for (auto I = ER.first, E = ER.second; I != E; ++I) {
116       SPIRVDBG(spvdbgs() << "[compare decorate] " << *Dec
117                         << " vs " << **I << " : ");
118       if (**I == *Dec)
119         return I;
120       SPIRVDBG(spvdbgs() << " diff\n");
121     }
122     SPIRVDBG(spvdbgs() << "[add decorate] " << *Dec << '\n');
123     return BaseType::insert(Dec);
124   }
125 };
126 
127 class SPIRVDecorate:public SPIRVDecorateGeneric{
128 public:
129   static const Op OC = OpDecorate;
130   static const SPIRVWord FixedWC = 3;
131   // Complete constructor for decorations without literals
SPIRVDecorate(Decoration TheDec,SPIRVEntry * TheTarget)132   SPIRVDecorate(Decoration TheDec, SPIRVEntry *TheTarget)
133     :SPIRVDecorateGeneric(OC, 3, TheDec, TheTarget){}
134   // Complete constructor for decorations with one word literal
SPIRVDecorate(Decoration TheDec,SPIRVEntry * TheTarget,SPIRVWord V)135   SPIRVDecorate(Decoration TheDec, SPIRVEntry *TheTarget, SPIRVWord V)
136     :SPIRVDecorateGeneric(OC, 4, TheDec, TheTarget, V){}
137   // Incomplete constructor
SPIRVDecorate()138   SPIRVDecorate():SPIRVDecorateGeneric(OC){}
139 
140   _SPIRV_DCL_ENCDEC
141   void setWordCount(SPIRVWord);
validate()142   void validate()const {
143     SPIRVDecorateGeneric::validate();
144     assert(WordCount == Literals.size() + FixedWC);
145   }
146 
147 };
148 
149 class SPIRVDecorateLinkageAttr:public SPIRVDecorate{
150 public:
151   // Complete constructor for LinkageAttributes decorations
SPIRVDecorateLinkageAttr(SPIRVEntry * TheTarget,const std::string & Name,SPIRVLinkageTypeKind Kind)152   SPIRVDecorateLinkageAttr(SPIRVEntry *TheTarget,
153       const std::string &Name, SPIRVLinkageTypeKind Kind)
154     :SPIRVDecorate(DecorationLinkageAttributes, TheTarget) {
155       for (auto &I:getVec(Name))
156         Literals.push_back(I);
157       Literals.push_back(Kind);
158       WordCount += Literals.size();
159     }
160   // Incomplete constructor
SPIRVDecorateLinkageAttr()161   SPIRVDecorateLinkageAttr():SPIRVDecorate(){}
162 
getLinkageName()163   std::string getLinkageName() const {
164     return getString(Literals.cbegin(), Literals.cend() - 1);
165   }
getLinkageType()166   SPIRVLinkageTypeKind getLinkageType() const {
167     return (SPIRVLinkageTypeKind)Literals.back();
168   }
169 
encodeLiterals(SPIRVEncoder & Encoder,const std::vector<SPIRVWord> & Literals)170   static void encodeLiterals(SPIRVEncoder& Encoder,
171                              const std::vector<SPIRVWord>& Literals) {
172 #ifdef _SPIRV_SUPPORT_TEXT_FMT
173     if(SPIRVUseTextFormat) {
174       Encoder << getString(Literals.cbegin(), Literals.cend() - 1);
175       Encoder.OS << " ";
176       Encoder << (SPIRVLinkageTypeKind)Literals.back();
177     } else
178 #endif
179      Encoder << Literals;
180   }
181 
decodeLiterals(SPIRVDecoder & Decoder,std::vector<SPIRVWord> & Literals)182   static void decodeLiterals(SPIRVDecoder& Decoder, std::vector<SPIRVWord>& Literals) {
183 #ifdef _SPIRV_SUPPORT_TEXT_FMT
184     if(SPIRVUseTextFormat) {
185       std::string Name;
186       Decoder >> Name;
187       SPIRVLinkageTypeKind Kind;
188       Decoder >> Kind;
189       std::copy_n(getVec(Name).begin(), Literals.size()-1, Literals.begin());
190       Literals.back() = Kind;
191    } else
192 #endif
193      Decoder >> Literals;
194   }
195 };
196 
197 class SPIRVMemberDecorate:public SPIRVDecorateGeneric{
198 public:
199   static const Op OC = OpMemberDecorate;
200   static const SPIRVWord FixedWC = 4;
201   // Complete constructor for decorations without literals
SPIRVMemberDecorate(Decoration TheDec,SPIRVWord Member,SPIRVEntry * TheTarget)202   SPIRVMemberDecorate(Decoration TheDec, SPIRVWord Member,
203       SPIRVEntry *TheTarget)
204     :SPIRVDecorateGeneric(OC, 4, TheDec, TheTarget),
205       MemberNumber(Member){}
206 
207   // Complete constructor for decorations with one word literal
SPIRVMemberDecorate(Decoration TheDec,SPIRVWord Member,SPIRVEntry * TheTarget,SPIRVWord V)208   SPIRVMemberDecorate(Decoration TheDec, SPIRVWord Member,
209       SPIRVEntry *TheTarget, SPIRVWord V)
210     :SPIRVDecorateGeneric(OC, 5, TheDec, TheTarget, V),
211       MemberNumber(Member){}
212 
213   // Incomplete constructor
SPIRVMemberDecorate()214   SPIRVMemberDecorate():SPIRVDecorateGeneric(OC), MemberNumber(SPIRVWORD_MAX){}
215 
getMemberNumber()216   SPIRVWord getMemberNumber() const { return MemberNumber;}
getPair()217   std::pair<SPIRVWord, Decoration> getPair() const {
218     return std::make_pair(MemberNumber, Dec);
219   }
220 
221   _SPIRV_DCL_ENCDEC
222   void setWordCount(SPIRVWord);
223 
validate()224   void validate()const {
225     SPIRVDecorateGeneric::validate();
226     assert(WordCount == Literals.size() + FixedWC);
227   }
228 protected:
229   SPIRVWord MemberNumber;
230 };
231 
232 class SPIRVDecorationGroup:public SPIRVEntry{
233 public:
234   static const Op OC = OpDecorationGroup;
235   static const SPIRVWord WC = 2;
236   // Complete constructor. Does not populate Decorations.
SPIRVDecorationGroup(SPIRVModule * TheModule,SPIRVId TheId)237   SPIRVDecorationGroup(SPIRVModule *TheModule, SPIRVId TheId)
238     :SPIRVEntry(TheModule, WC, OC, TheId){
239     validate();
240   };
241   // Incomplete constructor
SPIRVDecorationGroup()242   SPIRVDecorationGroup():SPIRVEntry(OC){}
243   void encodeAll(spv_ostream &O) const;
244   _SPIRV_DCL_ENCDEC
245   // Move the given decorates to the decoration group
takeDecorates(SPIRVDecorateSet & Decs)246   void takeDecorates(SPIRVDecorateSet &Decs) {
247     Decorations = std::move(Decs);
248     for (auto &I:Decorations)
249       const_cast<SPIRVDecorateGeneric *>(I)->setOwner(this);
250     Decs.clear();
251   }
252 
getDecorations()253   SPIRVDecorateSet& getDecorations() {
254     return Decorations;
255   }
256 
257 protected:
258   SPIRVDecorateSet Decorations;
validate()259   void validate()const {
260     assert(OpCode == OC);
261     assert(WordCount == WC);
262   }
263 };
264 
265 class SPIRVGroupDecorateGeneric:public SPIRVEntryNoIdGeneric{
266 public:
267   static const SPIRVWord FixedWC = 2;
268   // Complete constructor
SPIRVGroupDecorateGeneric(Op OC,SPIRVDecorationGroup * TheGroup,const std::vector<SPIRVId> & TheTargets)269   SPIRVGroupDecorateGeneric(Op OC, SPIRVDecorationGroup *TheGroup,
270       const std::vector<SPIRVId> &TheTargets)
271     :SPIRVEntryNoIdGeneric(TheGroup->getModule(), FixedWC + TheTargets.size(),
272         OC),
273      DecorationGroup(TheGroup), Targets(TheTargets){
274   }
275   // Incomplete constructor
SPIRVGroupDecorateGeneric(Op OC)276   SPIRVGroupDecorateGeneric(Op OC)
277     :SPIRVEntryNoIdGeneric(OC), DecorationGroup(nullptr){}
278 
setWordCount(SPIRVWord WC)279   void setWordCount(SPIRVWord WC) {
280     SPIRVEntryNoIdGeneric::setWordCount(WC);
281     Targets.resize(WC - FixedWC);
282   }
283   virtual void decorateTargets() = 0;
284   _SPIRV_DCL_ENCDEC
285 protected:
286   SPIRVDecorationGroup *DecorationGroup;
287   std::vector<SPIRVId> Targets;
288 };
289 
290 class SPIRVGroupDecorate:public SPIRVGroupDecorateGeneric{
291 public:
292   static const Op OC = OpGroupDecorate;
293   // Complete constructor
SPIRVGroupDecorate(SPIRVDecorationGroup * TheGroup,const std::vector<SPIRVId> & TheTargets)294   SPIRVGroupDecorate(SPIRVDecorationGroup *TheGroup,
295       const std::vector<SPIRVId> &TheTargets)
296     :SPIRVGroupDecorateGeneric(OC, TheGroup, TheTargets){}
297   // Incomplete constructor
SPIRVGroupDecorate()298   SPIRVGroupDecorate()
299     :SPIRVGroupDecorateGeneric(OC){}
300 
301   virtual void decorateTargets();
302 };
303 
304 class SPIRVGroupMemberDecorate:public SPIRVGroupDecorateGeneric{
305 public:
306   static const Op OC = OpGroupMemberDecorate;
307   // Complete constructor
SPIRVGroupMemberDecorate(SPIRVDecorationGroup * TheGroup,const std::vector<SPIRVId> & TheTargets)308   SPIRVGroupMemberDecorate(SPIRVDecorationGroup *TheGroup,
309       const std::vector<SPIRVId> &TheTargets)
310     :SPIRVGroupDecorateGeneric(OC, TheGroup, TheTargets){}
311   // Incomplete constructor
SPIRVGroupMemberDecorate()312   SPIRVGroupMemberDecorate()
313     :SPIRVGroupDecorateGeneric(OC){}
314 
315   virtual void decorateTargets();
316 };
317 
318 }
319 
320 
321 #endif /* SPIRVDECORATE_HPP_ */
322