Home | History | Annotate | Download | only in libSPIRV
      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 
     74   SPIRVDecorationGroup* getOwner() const {
     75     return Owner;
     76   }
     77 
     78   void setOwner(SPIRVDecorationGroup* owner) {
     79     Owner = owner;
     80   }
     81 
     82   SPIRVCapVec getRequiredCapability() const {
     83     return getCapability(Dec);
     84   }
     85 
     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;
    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
    132   SPIRVDecorate(Decoration TheDec, SPIRVEntry *TheTarget)
    133     :SPIRVDecorateGeneric(OC, 3, TheDec, TheTarget){}
    134   // Complete constructor for decorations with one word literal
    135   SPIRVDecorate(Decoration TheDec, SPIRVEntry *TheTarget, SPIRVWord V)
    136     :SPIRVDecorateGeneric(OC, 4, TheDec, TheTarget, V){}
    137   // Incomplete constructor
    138   SPIRVDecorate():SPIRVDecorateGeneric(OC){}
    139 
    140   _SPIRV_DCL_ENCDEC
    141   void setWordCount(SPIRVWord);
    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
    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
    161   SPIRVDecorateLinkageAttr():SPIRVDecorate(){}
    162 
    163   std::string getLinkageName() const {
    164     return getString(Literals.cbegin(), Literals.cend() - 1);
    165   }
    166   SPIRVLinkageTypeKind getLinkageType() const {
    167     return (SPIRVLinkageTypeKind)Literals.back();
    168   }
    169 
    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 
    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
    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
    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
    214   SPIRVMemberDecorate():SPIRVDecorateGeneric(OC), MemberNumber(SPIRVWORD_MAX){}
    215 
    216   SPIRVWord getMemberNumber() const { return MemberNumber;}
    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 
    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.
    237   SPIRVDecorationGroup(SPIRVModule *TheModule, SPIRVId TheId)
    238     :SPIRVEntry(TheModule, WC, OC, TheId){
    239     validate();
    240   };
    241   // Incomplete constructor
    242   SPIRVDecorationGroup():SPIRVEntry(OC){}
    243   void encodeAll(spv_ostream &O) const;
    244   _SPIRV_DCL_ENCDEC
    245   // Move the given decorates to the decoration group
    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 
    253   SPIRVDecorateSet& getDecorations() {
    254     return Decorations;
    255   }
    256 
    257 protected:
    258   SPIRVDecorateSet Decorations;
    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
    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
    276   SPIRVGroupDecorateGeneric(Op OC)
    277     :SPIRVEntryNoIdGeneric(OC), DecorationGroup(nullptr){}
    278 
    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
    294   SPIRVGroupDecorate(SPIRVDecorationGroup *TheGroup,
    295       const std::vector<SPIRVId> &TheTargets)
    296     :SPIRVGroupDecorateGeneric(OC, TheGroup, TheTargets){}
    297   // Incomplete constructor
    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
    308   SPIRVGroupMemberDecorate(SPIRVDecorationGroup *TheGroup,
    309       const std::vector<SPIRVId> &TheTargets)
    310     :SPIRVGroupDecorateGeneric(OC, TheGroup, TheTargets){}
    311   // Incomplete constructor
    312   SPIRVGroupMemberDecorate()
    313     :SPIRVGroupDecorateGeneric(OC){}
    314 
    315   virtual void decorateTargets();
    316 };
    317 
    318 }
    319 
    320 
    321 #endif /* SPIRVDECORATE_HPP_ */
    322