1//===- SPIRVDecorate.cpp -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 implements SPIR-V decorations.
37///
38//===----------------------------------------------------------------------===//
39
40#include "SPIRVDecorate.h"
41#include "SPIRVStream.h"
42#include "SPIRVValue.h"
43#include "SPIRVModule.h"
44
45namespace SPIRV{
46template<class T, class B>
47spv_ostream &
48operator<< (spv_ostream &O, const std::multiset<T *, B>& V) {
49  for (auto &I: V)
50    O << *I;
51  return O;
52}
53
54SPIRVDecorateGeneric::SPIRVDecorateGeneric(Op OC, SPIRVWord WC,
55                                           Decoration TheDec,
56                                           SPIRVEntry *TheTarget)
57    : SPIRVAnnotationGeneric(TheTarget->getModule(), WC, OC,
58                             TheTarget->getId()),
59      Dec(TheDec), Owner(nullptr) {
60  validate();
61  updateModuleVersion();
62}
63
64SPIRVDecorateGeneric::SPIRVDecorateGeneric(Op OC, SPIRVWord WC,
65                                           Decoration TheDec,
66                                           SPIRVEntry *TheTarget,
67                                           SPIRVWord V)
68    : SPIRVAnnotationGeneric(TheTarget->getModule(), WC, OC,
69                             TheTarget->getId()),
70      Dec(TheDec), Owner(nullptr) {
71  Literals.push_back(V);
72  validate();
73  updateModuleVersion();
74}
75
76SPIRVDecorateGeneric::SPIRVDecorateGeneric(Op OC)
77  :SPIRVAnnotationGeneric(OC), Dec(DecorationRelaxedPrecision), Owner(nullptr){
78}
79
80Decoration
81SPIRVDecorateGeneric::getDecorateKind()const {
82  return Dec;
83}
84
85SPIRVWord
86SPIRVDecorateGeneric::getLiteral(size_t i) const {
87  assert(0 <= i && i <= Literals.size() && "Out of bounds");
88  return Literals[i];
89}
90
91size_t
92SPIRVDecorateGeneric::getLiteralCount() const {
93  return Literals.size();
94}
95
96void
97SPIRVDecorate::encode(spv_ostream &O)const {
98  SPIRVEncoder Encoder = getEncoder(O);
99  Encoder << Target << Dec;
100  if ( Dec == DecorationLinkageAttributes )
101    SPIRVDecorateLinkageAttr::encodeLiterals(Encoder, Literals);
102  else
103    Encoder << Literals;
104}
105
106void
107SPIRVDecorate::setWordCount(SPIRVWord Count){
108  WordCount = Count;
109  Literals.resize(WordCount - FixedWC);
110}
111
112void
113SPIRVDecorate::decode(std::istream &I){
114  SPIRVDecoder Decoder = getDecoder(I);
115  Decoder >> Target >> Dec;
116  if(Dec == DecorationLinkageAttributes)
117    SPIRVDecorateLinkageAttr::decodeLiterals(Decoder, Literals);
118  else
119    Decoder >> Literals;
120  getOrCreateTarget()->addDecorate(this);
121}
122
123void
124SPIRVMemberDecorate::encode(spv_ostream &O)const {
125  getEncoder(O) << Target << MemberNumber << Dec << Literals;
126}
127
128void
129SPIRVMemberDecorate::setWordCount(SPIRVWord Count){
130  WordCount = Count;
131  Literals.resize(WordCount - FixedWC);
132}
133
134void
135SPIRVMemberDecorate::decode(std::istream &I){
136  getDecoder(I) >> Target >> MemberNumber >> Dec >> Literals;
137  getOrCreateTarget()->addMemberDecorate(this);
138}
139
140void
141SPIRVDecorationGroup::encode(spv_ostream &O)const {
142  getEncoder(O) << Id;
143}
144
145void
146SPIRVDecorationGroup::decode(std::istream &I){
147  getDecoder(I) >> Id;
148  Module->addDecorationGroup(this);
149}
150
151void
152SPIRVDecorationGroup::encodeAll(spv_ostream &O) const {
153  O << Decorations;
154  SPIRVEntry::encodeAll(O);
155}
156
157void
158SPIRVGroupDecorateGeneric::encode(spv_ostream &O)const {
159  getEncoder(O) << DecorationGroup << Targets;
160}
161
162void
163SPIRVGroupDecorateGeneric::decode(std::istream &I){
164  getDecoder(I) >> DecorationGroup >> Targets;
165  Module->addGroupDecorateGeneric(this);
166}
167
168void
169SPIRVGroupDecorate::decorateTargets() {
170  for(auto &I:Targets) {
171    auto Target = getOrCreate(I);
172    for (auto &Dec:DecorationGroup->getDecorations()) {
173      assert(Dec->isDecorate());
174      Target->addDecorate(static_cast<const SPIRVDecorate *const>(Dec));
175    }
176  }
177}
178
179void
180SPIRVGroupMemberDecorate::decorateTargets() {
181  for(auto &I:Targets) {
182    auto Target = getOrCreate(I);
183    for (auto &Dec:DecorationGroup->getDecorations()) {
184      assert(Dec->isMemberDecorate());
185      Target->addMemberDecorate(static_cast<const SPIRVMemberDecorate*>(Dec));
186    }
187  }
188}
189
190bool
191SPIRVDecorateGeneric::Comparator::operator()(const SPIRVDecorateGeneric *A,
192    const SPIRVDecorateGeneric *B) {
193  auto Action = [=](){
194  if (A->getOpCode() < B->getOpCode())
195    return true;
196  if (A->getOpCode() > B->getOpCode())
197    return false;
198  if (A->getDecorateKind() < B->getDecorateKind())
199    return true;
200  if (A->getDecorateKind() > B->getDecorateKind())
201    return false;
202  if (A->getLiteralCount() < B->getLiteralCount())
203    return true;
204  if (A->getLiteralCount() > B->getLiteralCount())
205    return false;
206  for (size_t I = 0, E = A->getLiteralCount(); I != E; ++I) {
207    auto EA = A->getLiteral(I);
208    auto EB = B->getLiteral(I);
209    if (EA < EB)
210      return true;
211    if (EA > EB)
212      return false;
213  }
214  return false;
215  };
216  auto Res = Action();
217  return Res;
218}
219
220bool operator==(const SPIRVDecorateGeneric &A, const SPIRVDecorateGeneric &B) {
221  if (A.getTargetId() != B.getTargetId())
222    return false;
223  if (A.getOpCode() != B.getOpCode())
224    return false;
225  if (A.getDecorateKind() != B.getDecorateKind())
226    return false;
227  if (A.getLiteralCount() != B.getLiteralCount())
228    return false;
229  for (size_t I = 0, E = A.getLiteralCount(); I != E; ++I) {
230    auto EA = A.getLiteral(I);
231    auto EB = B.getLiteral(I);
232    if (EA != EB)
233      return false;
234  }
235  return true;
236}
237}
238
239