C++程序  |  322行  |  10.15 KB

//===- SPIRVDecorate.h - SPIR-V Decorations ----------------------*- C++ -*-===//
//
//                     The LLVM/SPIRV Translator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
// Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal with the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimers.
// Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimers in the documentation
// and/or other materials provided with the distribution.
// Neither the names of Advanced Micro Devices, Inc., nor the names of its
// contributors may be used to endorse or promote products derived from this
// Software without specific prior written permission.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
// THE SOFTWARE.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This file defines SPIR-V decorations.
///
//===----------------------------------------------------------------------===//

#ifndef SPIRVDECORATE_HPP_
#define SPIRVDECORATE_HPP_

#include "SPIRVEntry.h"
#include "SPIRVUtil.h"
#include "SPIRVStream.h"
#include <string>
#include <vector>
#include <utility>

namespace SPIRV{
class SPIRVDecorationGroup;
class SPIRVDecorateGeneric:public SPIRVAnnotationGeneric{
public:
  // Complete constructor for decorations without literals
  SPIRVDecorateGeneric(Op OC, SPIRVWord WC, Decoration TheDec,
      SPIRVEntry *TheTarget);
  // Complete constructor for decorations with one word literal
  SPIRVDecorateGeneric(Op OC, SPIRVWord WC, Decoration TheDec,
      SPIRVEntry *TheTarget, SPIRVWord V);
  // Incomplete constructor
  SPIRVDecorateGeneric(Op OC);

  SPIRVWord getLiteral(size_t) const;
  Decoration getDecorateKind() const;
  size_t getLiteralCount() const;
  /// Compare for kind and literal only.
  struct Comparator {
    bool operator()(const SPIRVDecorateGeneric *A, const SPIRVDecorateGeneric *B);
  };
  /// Compare kind, literals and target.
  friend bool operator==(const SPIRVDecorateGeneric &A,
      const SPIRVDecorateGeneric &B);

  SPIRVDecorationGroup* getOwner() const {
    return Owner;
  }

  void setOwner(SPIRVDecorationGroup* owner) {
    Owner = owner;
  }

  SPIRVCapVec getRequiredCapability() const {
    return getCapability(Dec);
  }

  SPIRVWord getRequiredSPIRVVersion() const override {
    switch (Dec) {
    case DecorationSpecId:
      if (getModule()->hasCapability(CapabilityKernel))
        return SPIRV_1_1;
      else
        return SPIRV_1_0;

    case DecorationMaxByteOffset:
      return SPIRV_1_1;

    default:
      return SPIRV_1_0;
    }
  }

protected:
  Decoration Dec;
  std::vector<SPIRVWord> Literals;
  SPIRVDecorationGroup *Owner; // Owning decorate group
};

class SPIRVDecorateSet: public std::multiset<const SPIRVDecorateGeneric *,
    SPIRVDecorateGeneric::Comparator> {
    public:
  typedef std::multiset<const SPIRVDecorateGeneric *,
      SPIRVDecorateGeneric::Comparator> BaseType;
  iterator insert(const value_type& Dec) {
    auto ER = BaseType::equal_range(Dec);
    for (auto I = ER.first, E = ER.second; I != E; ++I) {
      SPIRVDBG(spvdbgs() << "[compare decorate] " << *Dec
                        << " vs " << **I << " : ");
      if (**I == *Dec)
        return I;
      SPIRVDBG(spvdbgs() << " diff\n");
    }
    SPIRVDBG(spvdbgs() << "[add decorate] " << *Dec << '\n');
    return BaseType::insert(Dec);
  }
};

class SPIRVDecorate:public SPIRVDecorateGeneric{
public:
  static const Op OC = OpDecorate;
  static const SPIRVWord FixedWC = 3;
  // Complete constructor for decorations without literals
  SPIRVDecorate(Decoration TheDec, SPIRVEntry *TheTarget)
    :SPIRVDecorateGeneric(OC, 3, TheDec, TheTarget){}
  // Complete constructor for decorations with one word literal
  SPIRVDecorate(Decoration TheDec, SPIRVEntry *TheTarget, SPIRVWord V)
    :SPIRVDecorateGeneric(OC, 4, TheDec, TheTarget, V){}
  // Incomplete constructor
  SPIRVDecorate():SPIRVDecorateGeneric(OC){}

  _SPIRV_DCL_ENCDEC
  void setWordCount(SPIRVWord);
  void validate()const {
    SPIRVDecorateGeneric::validate();
    assert(WordCount == Literals.size() + FixedWC);
  }

};

class SPIRVDecorateLinkageAttr:public SPIRVDecorate{
public:
  // Complete constructor for LinkageAttributes decorations
  SPIRVDecorateLinkageAttr(SPIRVEntry *TheTarget,
      const std::string &Name, SPIRVLinkageTypeKind Kind)
    :SPIRVDecorate(DecorationLinkageAttributes, TheTarget) {
      for (auto &I:getVec(Name))
        Literals.push_back(I);
      Literals.push_back(Kind);
      WordCount += Literals.size();
    }
  // Incomplete constructor
  SPIRVDecorateLinkageAttr():SPIRVDecorate(){}

  std::string getLinkageName() const {
    return getString(Literals.cbegin(), Literals.cend() - 1);
  }
  SPIRVLinkageTypeKind getLinkageType() const {
    return (SPIRVLinkageTypeKind)Literals.back();
  }

  static void encodeLiterals(SPIRVEncoder& Encoder,
                             const std::vector<SPIRVWord>& Literals) {
#ifdef _SPIRV_SUPPORT_TEXT_FMT
    if(SPIRVUseTextFormat) {
      Encoder << getString(Literals.cbegin(), Literals.cend() - 1);
      Encoder.OS << " ";
      Encoder << (SPIRVLinkageTypeKind)Literals.back();
    } else
#endif
     Encoder << Literals;
  }

  static void decodeLiterals(SPIRVDecoder& Decoder, std::vector<SPIRVWord>& Literals) {
#ifdef _SPIRV_SUPPORT_TEXT_FMT
    if(SPIRVUseTextFormat) {
      std::string Name;
      Decoder >> Name;
      SPIRVLinkageTypeKind Kind;
      Decoder >> Kind;
      std::copy_n(getVec(Name).begin(), Literals.size()-1, Literals.begin());
      Literals.back() = Kind;
   } else
#endif
     Decoder >> Literals;
  }
};

class SPIRVMemberDecorate:public SPIRVDecorateGeneric{
public:
  static const Op OC = OpMemberDecorate;
  static const SPIRVWord FixedWC = 4;
  // Complete constructor for decorations without literals
  SPIRVMemberDecorate(Decoration TheDec, SPIRVWord Member,
      SPIRVEntry *TheTarget)
    :SPIRVDecorateGeneric(OC, 4, TheDec, TheTarget),
      MemberNumber(Member){}

  // Complete constructor for decorations with one word literal
  SPIRVMemberDecorate(Decoration TheDec, SPIRVWord Member,
      SPIRVEntry *TheTarget, SPIRVWord V)
    :SPIRVDecorateGeneric(OC, 5, TheDec, TheTarget, V),
      MemberNumber(Member){}

  // Incomplete constructor
  SPIRVMemberDecorate():SPIRVDecorateGeneric(OC), MemberNumber(SPIRVWORD_MAX){}

  SPIRVWord getMemberNumber() const { return MemberNumber;}
  std::pair<SPIRVWord, Decoration> getPair() const {
    return std::make_pair(MemberNumber, Dec);
  }

  _SPIRV_DCL_ENCDEC
  void setWordCount(SPIRVWord);

  void validate()const {
    SPIRVDecorateGeneric::validate();
    assert(WordCount == Literals.size() + FixedWC);
  }
protected:
  SPIRVWord MemberNumber;
};

class SPIRVDecorationGroup:public SPIRVEntry{
public:
  static const Op OC = OpDecorationGroup;
  static const SPIRVWord WC = 2;
  // Complete constructor. Does not populate Decorations.
  SPIRVDecorationGroup(SPIRVModule *TheModule, SPIRVId TheId)
    :SPIRVEntry(TheModule, WC, OC, TheId){
    validate();
  };
  // Incomplete constructor
  SPIRVDecorationGroup():SPIRVEntry(OC){}
  void encodeAll(spv_ostream &O) const;
  _SPIRV_DCL_ENCDEC
  // Move the given decorates to the decoration group
  void takeDecorates(SPIRVDecorateSet &Decs) {
    Decorations = std::move(Decs);
    for (auto &I:Decorations)
      const_cast<SPIRVDecorateGeneric *>(I)->setOwner(this);
    Decs.clear();
  }

  SPIRVDecorateSet& getDecorations() {
    return Decorations;
  }

protected:
  SPIRVDecorateSet Decorations;
  void validate()const {
    assert(OpCode == OC);
    assert(WordCount == WC);
  }
};

class SPIRVGroupDecorateGeneric:public SPIRVEntryNoIdGeneric{
public:
  static const SPIRVWord FixedWC = 2;
  // Complete constructor
  SPIRVGroupDecorateGeneric(Op OC, SPIRVDecorationGroup *TheGroup,
      const std::vector<SPIRVId> &TheTargets)
    :SPIRVEntryNoIdGeneric(TheGroup->getModule(), FixedWC + TheTargets.size(),
        OC),
     DecorationGroup(TheGroup), Targets(TheTargets){
  }
  // Incomplete constructor
  SPIRVGroupDecorateGeneric(Op OC)
    :SPIRVEntryNoIdGeneric(OC), DecorationGroup(nullptr){}

  void setWordCount(SPIRVWord WC) {
    SPIRVEntryNoIdGeneric::setWordCount(WC);
    Targets.resize(WC - FixedWC);
  }
  virtual void decorateTargets() = 0;
  _SPIRV_DCL_ENCDEC
protected:
  SPIRVDecorationGroup *DecorationGroup;
  std::vector<SPIRVId> Targets;
};

class SPIRVGroupDecorate:public SPIRVGroupDecorateGeneric{
public:
  static const Op OC = OpGroupDecorate;
  // Complete constructor
  SPIRVGroupDecorate(SPIRVDecorationGroup *TheGroup,
      const std::vector<SPIRVId> &TheTargets)
    :SPIRVGroupDecorateGeneric(OC, TheGroup, TheTargets){}
  // Incomplete constructor
  SPIRVGroupDecorate()
    :SPIRVGroupDecorateGeneric(OC){}

  virtual void decorateTargets();
};

class SPIRVGroupMemberDecorate:public SPIRVGroupDecorateGeneric{
public:
  static const Op OC = OpGroupMemberDecorate;
  // Complete constructor
  SPIRVGroupMemberDecorate(SPIRVDecorationGroup *TheGroup,
      const std::vector<SPIRVId> &TheTargets)
    :SPIRVGroupDecorateGeneric(OC, TheGroup, TheTargets){}
  // Incomplete constructor
  SPIRVGroupMemberDecorate()
    :SPIRVGroupDecorateGeneric(OC){}

  virtual void decorateTargets();
};

}


#endif /* SPIRVDECORATE_HPP_ */