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