1//===- SPIRVStream.h � 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 defines Word class for SPIR-V.
37///
38//===----------------------------------------------------------------------===//
39
40#ifndef SPIRVSTREAM_H
41#define SPIRVSTREAM_H
42
43#include "SPIRVDebug.h"
44#include "SPIRVModule.h"
45#include "SPIRVExtInst.h"
46#include <algorithm>
47#include <cstdint>
48#include <iostream>
49#include <iterator>
50#include <vector>
51#include <string>
52
53namespace SPIRV{
54
55#ifndef _SPIRV_SUPPORT_TEXT_FMT
56#define _SPIRV_SUPPORT_TEXT_FMT
57#endif
58
59#ifdef _SPIRV_SUPPORT_TEXT_FMT
60// Use textual format for SPIRV.
61extern bool SPIRVUseTextFormat;
62#endif
63
64class SPIRVFunction;
65class SPIRVBasicBlock;
66
67class SPIRVDecoder {
68public:
69  SPIRVDecoder(std::istream& InputStream, SPIRVModule& Module)
70    :IS(InputStream), M(Module), WordCount(0), OpCode(OpNop),
71     Scope(NULL){}
72  SPIRVDecoder(std::istream& InputStream, SPIRVFunction& F);
73  SPIRVDecoder(std::istream& InputStream, SPIRVBasicBlock &BB);
74
75  void setScope(SPIRVEntry *);
76  bool getWordCountAndOpCode();
77  SPIRVEntry *getEntry();
78  void validate()const;
79
80  std::istream &IS;
81  SPIRVModule &M;
82  SPIRVWord WordCount;
83  Op OpCode;
84  SPIRVEntry *Scope; // A function or basic block
85};
86
87class SPIRVEncoder {
88public:
89  explicit SPIRVEncoder(spv_ostream &OutputStream) : OS(OutputStream) {}
90  spv_ostream &OS;
91};
92
93/// Output a new line in text mode. Do nothing in binary mode.
94class SPIRVNL {
95  friend spv_ostream &operator<<(spv_ostream &O, const SPIRVNL &E);
96};
97
98template<typename T>
99const SPIRVDecoder&
100DecodeBinary(const SPIRVDecoder& I, T &V) {
101  uint32_t W;
102  I.IS.read(reinterpret_cast<char*>(&W), sizeof(W));
103  V = static_cast<T>(W);
104  SPIRVDBG(spvdbgs() << "Read word: W = " << W << " V = " << V << '\n');
105  return I;
106}
107
108template<typename T>
109const SPIRVDecoder&
110operator>>(const SPIRVDecoder& I, T &V) {
111#ifdef _SPIRV_SUPPORT_TEXT_FMT
112  if (SPIRVUseTextFormat) {
113    uint32_t W;
114    I.IS >> W;
115    V = static_cast<T>(W);
116    SPIRVDBG(spvdbgs() << "Read word: W = " << W << " V = " << V << '\n');
117    return I;
118  }
119#endif
120  return DecodeBinary(I, V);
121}
122
123template<typename T>
124const SPIRVDecoder&
125operator>>(const SPIRVDecoder& I, T *&P) {
126  SPIRVId Id;
127  I >> Id;
128  P = static_cast<T*>(I.M.getEntry(Id));
129  return I;
130}
131
132template<typename IterTy>
133const SPIRVDecoder&
134operator>>(const SPIRVDecoder& Decoder, const std::pair<IterTy,IterTy> &Range) {
135  for (IterTy I = Range.first, E = Range.second; I != E; ++I)
136    Decoder >> *I;
137  return Decoder;
138}
139
140template<typename T>
141const SPIRVDecoder&
142operator>>(const SPIRVDecoder& I, std::vector<T> &V) {
143  for (size_t i = 0, e = V.size(); i != e; ++i)
144    I >> V[i];
145  return I;
146}
147
148template<typename T>
149const SPIRVEncoder&
150operator<<(const SPIRVEncoder& O, T V) {
151#ifdef _SPIRV_SUPPORT_TEXT_FMT
152  if (SPIRVUseTextFormat) {
153    O.OS << V << " ";
154    return O;
155  }
156#endif
157  uint32_t W = static_cast<uint32_t>(V);
158  O.OS.write(reinterpret_cast<char*>(&W), sizeof(W));
159  return O;
160}
161
162template<typename T>
163const SPIRVEncoder&
164operator<<(const SPIRVEncoder& O, T* P) {
165  return O << P->getId();
166}
167
168template<typename T>
169const SPIRVEncoder&
170operator<<(const SPIRVEncoder& O, const std::vector<T>& V) {
171  for (size_t i = 0, e = V.size(); i != e; ++i)
172    O << V[i];
173  return O;
174}
175
176template<typename IterTy>
177const SPIRVEncoder&
178operator<<(const SPIRVEncoder& Encoder, const std::pair<IterTy,IterTy> &Range) {
179  for (IterTy I = Range.first, E = Range.second; I != E; ++I)
180    Encoder << *I;
181  return Encoder;
182}
183
184#define SPIRV_DEC_ENCDEC(Type) \
185const SPIRVEncoder& \
186operator<<(const SPIRVEncoder& O, Type V); \
187const SPIRVDecoder& \
188operator>>(const SPIRVDecoder& I, Type &V);
189
190SPIRV_DEC_ENCDEC(Op)
191SPIRV_DEC_ENCDEC(Capability)
192SPIRV_DEC_ENCDEC(Decoration)
193SPIRV_DEC_ENCDEC(OCLExtOpKind)
194SPIRV_DEC_ENCDEC(LinkageType)
195
196const SPIRVEncoder&
197operator<<(const SPIRVEncoder&O, const std::string& Str);
198const SPIRVDecoder&
199operator>>(const SPIRVDecoder&I, std::string& Str);
200
201} // namespace SPIRV
202#endif
203