• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- SPIRVStream.cpp � Class to represent a SPIR-V Stream ------*- 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 stream class.
37 ///
38 //===----------------------------------------------------------------------===//
39 #include "SPIRVDebug.h"
40 #include "SPIRVStream.h"
41 #include "SPIRVFunction.h"
42 #include "SPIRVOpCode.h"
43 #include "SPIRVNameMapEnum.h"
44 
45 namespace SPIRV{
46 
47 /// Write string with quote. Replace " with \".
writeQuotedString(spv_ostream & O,const std::string & Str)48 static void writeQuotedString(spv_ostream& O, const std::string& Str) {
49   O << '"';
50   for (auto I : Str) {
51     if (I == '"')
52       O << '\\';
53     O << I;
54   }
55   O << '"';
56 }
57 
58 /// Read quoted string. Replace \" with ".
readQuotedString(std::istream & IS,std::string & Str)59 static void readQuotedString(std::istream &IS, std::string& Str) {
60   char Ch = ' ';
61   char PreCh = ' ';
62   while (IS >> Ch && Ch != '"')
63     ;
64 
65   if (IS >> PreCh && PreCh != '"') {
66     while (IS >> Ch) {
67       if (Ch == '"') {
68         if (PreCh != '\\') {
69           Str += PreCh;
70           break;
71         }
72         else
73           PreCh = Ch;
74       } else {
75         Str += PreCh;
76         PreCh = Ch;
77       }
78     }
79   }
80 }
81 
82 #ifdef _SPIRV_SUPPORT_TEXT_FMT
83 bool SPIRVUseTextFormat = false;
84 #endif
85 
SPIRVDecoder(std::istream & InputStream,SPIRVFunction & F)86 SPIRVDecoder::SPIRVDecoder(std::istream &InputStream, SPIRVFunction &F)
87   :IS(InputStream), M(*F.getModule()), WordCount(0), OpCode(OpNop),
88    Scope(&F){}
89 
SPIRVDecoder(std::istream & InputStream,SPIRVBasicBlock & BB)90 SPIRVDecoder::SPIRVDecoder(std::istream &InputStream, SPIRVBasicBlock &BB)
91   :IS(InputStream), M(*BB.getModule()), WordCount(0), OpCode(OpNop),
92    Scope(&BB){}
93 
94 void
setScope(SPIRVEntry * TheScope)95 SPIRVDecoder::setScope(SPIRVEntry *TheScope) {
96   assert(TheScope && (TheScope->getOpCode() == OpFunction ||
97       TheScope->getOpCode() == OpLabel));
98   Scope = TheScope;
99 }
100 
101 template<class T>
102 const SPIRVDecoder&
decode(const SPIRVDecoder & I,T & V)103 decode(const SPIRVDecoder& I, T &V) {
104 #ifdef _SPIRV_SUPPORT_TEXT_FMT
105   if (SPIRVUseTextFormat) {
106     std::string W;
107     I.IS >> W;
108     V = getNameMap(V).rmap(W);
109     SPIRVDBG(spvdbgs() << "Read word: W = " << W << " V = " << V << '\n');
110     return I;
111   }
112 #endif
113   return DecodeBinary(I, V);
114 }
115 
116 template<class T>
117 const SPIRVEncoder&
encode(const SPIRVEncoder & O,T V)118 encode(const SPIRVEncoder& O, T V) {
119 #ifdef _SPIRV_SUPPORT_TEXT_FMT
120   if (SPIRVUseTextFormat) {
121     O.OS << getNameMap(V).map(V) << " ";
122     return O;
123   }
124 #endif
125   return O << static_cast<SPIRVWord>(V);
126 }
127 
128 #define SPIRV_DEF_ENCDEC(Type) \
129 const SPIRVDecoder& \
130 operator>>(const SPIRVDecoder& I, Type &V) { \
131   return decode(I, V); \
132 }\
133 const SPIRVEncoder& \
134 operator<<(const SPIRVEncoder& O, Type V) { \
135   return encode(O, V); \
136 }
137 
138 SPIRV_DEF_ENCDEC(Op)
SPIRV_DEF_ENCDEC(Capability)139 SPIRV_DEF_ENCDEC(Capability)
140 SPIRV_DEF_ENCDEC(Decoration)
141 SPIRV_DEF_ENCDEC(OCLExtOpKind)
142 SPIRV_DEF_ENCDEC(LinkageType)
143 
144 // Read a string with padded 0's at the end so that they form a stream of
145 // words.
146 const SPIRVDecoder&
147 operator>>(const SPIRVDecoder&I, std::string& Str) {
148 #ifdef _SPIRV_SUPPORT_TEXT_FMT
149   if (SPIRVUseTextFormat) {
150     readQuotedString(I.IS, Str);
151     SPIRVDBG(spvdbgs() << "Read string: \"" << Str << "\"\n");
152     return I;
153   }
154 #endif
155 
156   uint64_t Count = 0;
157   char Ch;
158   while (I.IS.get(Ch) && Ch != '\0') {
159     Str += Ch;
160     ++Count;
161   }
162   Count = (Count + 1) % 4;
163   Count = Count ? 4 - Count : 0;
164   for (;Count; --Count) {
165     I.IS >> Ch;
166     assert(Ch == '\0' && "Invalid string in SPIRV");
167   }
168   SPIRVDBG(spvdbgs() << "Read string: \"" << Str << "\"\n");
169   return I;
170 }
171 
172 // Write a string with padded 0's at the end so that they form a stream of
173 // words.
174 const SPIRVEncoder&
operator <<(const SPIRVEncoder & O,const std::string & Str)175 operator<<(const SPIRVEncoder&O, const std::string& Str) {
176 #ifdef _SPIRV_SUPPORT_TEXT_FMT
177   if (SPIRVUseTextFormat) {
178     writeQuotedString(O.OS, Str);
179     return O;
180   }
181 #endif
182 
183   size_t L = Str.length();
184   O.OS.write(Str.c_str(), L);
185   char Zeros[4] = {0, 0, 0, 0};
186   O.OS.write(Zeros, 4-L%4);
187   return O;
188 }
189 
190 bool
getWordCountAndOpCode()191 SPIRVDecoder::getWordCountAndOpCode() {
192   if (IS.eof()) {
193     WordCount = 0;
194     OpCode = OpNop;
195     SPIRVDBG(spvdbgs() << "[SPIRVDecoder] getWordCountAndOpCode EOF " <<
196         WordCount << " " << OpCode << '\n');
197     return false;
198   }
199 #ifdef _SPIRV_SUPPORT_TEXT_FMT
200   if (SPIRVUseTextFormat) {
201     *this >> WordCount;
202     assert(!IS.bad() && "SPIRV stream is bad");
203     if (IS.fail()) {
204       WordCount = 0;
205       OpCode = OpNop;
206       SPIRVDBG(spvdbgs() << "[SPIRVDecoder] getWordCountAndOpCode FAIL " <<
207           WordCount << " " << OpCode << '\n');
208       return false;
209     }
210     *this >> OpCode;
211   } else {
212 #endif
213   SPIRVWord WordCountAndOpCode;
214   *this >> WordCountAndOpCode;
215   WordCount = WordCountAndOpCode >> 16;
216   OpCode = static_cast<Op>(WordCountAndOpCode & 0xFFFF);
217 #ifdef _SPIRV_SUPPORT_TEXT_FMT
218   }
219 #endif
220   assert(!IS.bad() && "SPIRV stream is bad");
221   if (IS.fail()) {
222     WordCount = 0;
223     OpCode = OpNop;
224     SPIRVDBG(spvdbgs() << "[SPIRVDecoder] getWordCountAndOpCode FAIL " <<
225         WordCount << " " << OpCode << '\n');
226     return false;
227   }
228   SPIRVDBG(spvdbgs() << "[SPIRVDecoder] getWordCountAndOpCode " << WordCount <<
229       " " << OpCodeNameMap::map(OpCode) << '\n');
230   return true;
231 }
232 
233 SPIRVEntry *
getEntry()234 SPIRVDecoder::getEntry() {
235   if (WordCount == 0 || OpCode == OpNop)
236     return NULL;
237   SPIRVEntry *Entry = SPIRVEntry::create(OpCode);
238   assert(Entry);
239   Entry->setModule(&M);
240   if (isModuleScopeAllowedOpCode(OpCode) && !Scope) {}
241   else
242     Entry->setScope(Scope);
243   Entry->setWordCount(WordCount);
244   IS >> *Entry;
245   assert(!IS.bad() && !IS.fail() && "SPIRV stream fails");
246   M.add(Entry);
247   return Entry;
248 }
249 
250 void
validate() const251 SPIRVDecoder::validate()const {
252   assert(OpCode != OpNop && "Invalid op code");
253   assert(WordCount && "Invalid word count");
254   assert(!IS.bad() && "Bad iInput stream");
255 }
256 
257 spv_ostream &
operator <<(spv_ostream & O,const SPIRVNL & E)258 operator<<(spv_ostream &O, const SPIRVNL &E) {
259 #ifdef _SPIRV_SUPPORT_TEXT_FMT
260   if (SPIRVUseTextFormat)
261     O << '\n';
262 #endif
263   return O;
264 }
265 
266 } // end of SPIRV namespace
267 
268