SPIRVEntry.cpp revision c5130a58e2c3c4d66fa2b843aefadaab8cf6fb19
1//===- SPIRVEntry.cpp - Base Class for SPIR-V Entities -----------*- 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 base class for SPIR-V entities.
37///
38//===----------------------------------------------------------------------===//
39
40#include "SPIRVEntry.h"
41#include "SPIRVDebug.h"
42#include "SPIRVType.h"
43#include "SPIRVFunction.h"
44#include "SPIRVBasicBlock.h"
45#include "SPIRVInstruction.h"
46#include "SPIRVDecorate.h"
47#include "SPIRVStream.h"
48
49#include <algorithm>
50#include <map>
51#include <set>
52#include <sstream>
53#include <string>
54#include <utility>
55
56using namespace SPIRV;
57
58namespace SPIRV{
59
60template<typename T>
61SPIRVEntry* create() {
62  return new T();
63}
64
65SPIRVEntry *
66SPIRVEntry::create(Op OpCode) {
67  typedef SPIRVEntry *(*SPIRVFactoryTy)();
68  struct TableEntry {
69    Op Opn;
70    SPIRVFactoryTy Factory;
71    operator std::pair<const Op, SPIRVFactoryTy>() {
72      return std::make_pair(Opn, Factory);
73    }
74  };
75
76  static TableEntry Table[] = {
77#define _SPIRV_OP(x,...) {Op##x, &SPIRV::create<SPIRV##x>},
78#include "SPIRVOpCodeEnum.h"
79#undef _SPIRV_OP
80  };
81
82  typedef std::map<Op, SPIRVFactoryTy> OpToFactoryMapTy;
83  static const OpToFactoryMapTy OpToFactoryMap(std::begin(Table),
84      std::end(Table));
85
86  OpToFactoryMapTy::const_iterator Loc = OpToFactoryMap.find(OpCode);
87  if (Loc != OpToFactoryMap.end())
88    return Loc->second();
89
90  SPIRVDBG(spvdbgs() << "No factory for OpCode " << (unsigned)OpCode << '\n';)
91  assert (0 && "Not implemented");
92  return 0;
93}
94
95std::unique_ptr<SPIRV::SPIRVEntry>
96SPIRVEntry::create_unique(Op OC) {
97  return std::unique_ptr<SPIRVEntry>(create(OC));
98}
99
100std::unique_ptr<SPIRV::SPIRVExtInst>
101SPIRVEntry::create_unique(SPIRVExtInstSetKind Set,
102    unsigned ExtOp) {
103  return std::unique_ptr<SPIRVExtInst>(new SPIRVExtInst(Set, ExtOp));
104}
105
106SPIRVErrorLog &
107SPIRVEntry::getErrorLog()const {
108  return Module->getErrorLog();
109}
110
111bool
112SPIRVEntry::exist(SPIRVId TheId)const {
113  return Module->exist(TheId);
114}
115
116SPIRVEntry *
117SPIRVEntry::getOrCreate(SPIRVId TheId)const {
118  SPIRVEntry *Entry = nullptr;
119  bool Found = Module->exist(TheId, &Entry);
120  if (!Found)
121    return Module->addForward(TheId, nullptr);
122  return Entry;
123}
124
125SPIRVValue *
126SPIRVEntry::getValue(SPIRVId TheId)const {
127  return get<SPIRVValue>(TheId);
128}
129
130SPIRVType *
131SPIRVEntry::getValueType(SPIRVId TheId)const {
132  return get<SPIRVValue>(TheId)->getType();
133}
134
135SPIRVEncoder
136SPIRVEntry::getEncoder(spv_ostream &O)const{
137  return SPIRVEncoder(O);
138}
139
140SPIRVDecoder
141SPIRVEntry::getDecoder(std::istream& I){
142  return SPIRVDecoder(I, *Module);
143}
144
145void
146SPIRVEntry::setWordCount(SPIRVWord TheWordCount){
147  WordCount = TheWordCount;
148}
149
150void
151SPIRVEntry::setName(const std::string& TheName) {
152  Name = TheName;
153  SPIRVDBG(spvdbgs() << "Set name for obj " << Id << " " <<
154    Name << '\n');
155}
156
157void
158SPIRVEntry::setModule(SPIRVModule *TheModule) {
159  assert(TheModule && "Invalid module");
160  if (TheModule == Module)
161    return;
162  assert(Module == NULL && "Cannot change owner of entry");
163  Module = TheModule;
164}
165
166void
167SPIRVEntry::encode(spv_ostream &O) const {
168  assert (0 && "Not implemented");
169}
170
171void
172SPIRVEntry::encodeName(spv_ostream &O) const {
173  if (!Name.empty())
174    O << SPIRVName(this, Name);
175}
176
177void
178SPIRVEntry::encodeAll(spv_ostream &O) const {
179  encodeWordCountOpCode(O);
180  encode(O);
181  encodeChildren(O);
182}
183
184void
185SPIRVEntry::encodeChildren(spv_ostream &O)const {
186}
187
188void
189SPIRVEntry::encodeWordCountOpCode(spv_ostream &O) const {
190#ifdef _SPIRV_SUPPORT_TEXT_FMT
191  if (SPIRVUseTextFormat) {
192    getEncoder(O) << WordCount << OpCode;
193    return;
194  }
195#endif
196  getEncoder(O) << mkWord(WordCount, OpCode);
197}
198// Read words from SPIRV binary and create members for SPIRVEntry.
199// The word count and op code has already been read before calling this
200// function for creating the SPIRVEntry. Therefore the input stream only
201// contains the remaining part of the words for the SPIRVEntry.
202void
203SPIRVEntry::decode(std::istream &I) {
204  assert (0 && "Not implemented");
205}
206
207std::vector<SPIRVValue *>
208SPIRVEntry::getValues(const std::vector<SPIRVId>& IdVec)const {
209  std::vector<SPIRVValue *> ValueVec;
210  for (auto i:IdVec)
211    ValueVec.push_back(getValue(i));
212  return ValueVec;
213}
214
215std::vector<SPIRVType *>
216SPIRVEntry::getValueTypes(const std::vector<SPIRVId>& IdVec)const {
217  std::vector<SPIRVType *> TypeVec;
218  for (auto i:IdVec)
219    TypeVec.push_back(getValue(i)->getType());
220  return TypeVec;
221}
222
223std::vector<SPIRVId>
224SPIRVEntry::getIds(const std::vector<SPIRVValue *> ValueVec)const {
225  std::vector<SPIRVId> IdVec;
226  for (auto i:ValueVec)
227    IdVec.push_back(i->getId());
228  return IdVec;
229}
230
231SPIRVEntry *
232SPIRVEntry::getEntry(SPIRVId TheId) const {
233  return Module->getEntry(TheId);
234}
235
236void
237SPIRVEntry::validateFunctionControlMask(SPIRVWord TheFCtlMask)
238  const {
239  SPIRVCK(isValidFunctionControlMask(TheFCtlMask),
240      InvalidFunctionControlMask, "");
241}
242
243void
244SPIRVEntry::validateValues(const std::vector<SPIRVId> &Ids)const {
245  for (auto I:Ids)
246    getValue(I)->validate();
247}
248
249void
250SPIRVEntry::validateBuiltin(SPIRVWord TheSet, SPIRVWord Index)const {
251  (void) TheSet;
252  (void) Index;
253  assert(TheSet != SPIRVWORD_MAX && Index != SPIRVWORD_MAX &&
254      "Invalid builtin");
255}
256
257void
258SPIRVEntry::addDecorate(const SPIRVDecorate *Dec){
259  Decorates.insert(std::make_pair(Dec->getDecorateKind(), Dec));
260  Module->addDecorate(Dec);
261  SPIRVDBG(spvdbgs() << "[addDecorate] " << *Dec << '\n';)
262}
263
264void
265SPIRVEntry::addDecorate(Decoration Kind) {
266  addDecorate(new SPIRVDecorate(Kind, this));
267}
268
269void
270SPIRVEntry::addDecorate(Decoration Kind, SPIRVWord Literal) {
271  addDecorate(new SPIRVDecorate(Kind, this, Literal));
272}
273
274void
275SPIRVEntry::eraseDecorate(Decoration Dec){
276  Decorates.erase(Dec);
277}
278
279void
280SPIRVEntry::takeDecorates(SPIRVEntry *E){
281  Decorates = std::move(E->Decorates);
282  SPIRVDBG(spvdbgs() << "[takeDecorates] " << Id << '\n';)
283}
284
285void
286SPIRVEntry::setLine(SPIRVLine *L){
287  Line = L;
288  L->setTargetId(Id);
289  SPIRVDBG(spvdbgs() << "[setLine] " << *L << '\n';)
290}
291
292void
293SPIRVEntry::takeLine(SPIRVEntry *E){
294  Line = E->Line;
295  if (Line == nullptr)
296    return;
297  Line->setTargetId(Id);
298  E->Line = nullptr;
299}
300
301void
302SPIRVEntry::addMemberDecorate(const SPIRVMemberDecorate *Dec){
303  assert(canHaveMemberDecorates() && MemberDecorates.find(Dec->getPair()) ==
304      MemberDecorates.end());
305  MemberDecorates[Dec->getPair()] = Dec;
306  Module->addDecorate(Dec);
307  SPIRVDBG(spvdbgs() << "[addMemberDecorate] " << *Dec << '\n';)
308}
309
310void
311SPIRVEntry::addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind) {
312  addMemberDecorate(new SPIRVMemberDecorate(Kind, MemberNumber, this));
313}
314
315void
316SPIRVEntry::addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind,
317    SPIRVWord Literal) {
318  addMemberDecorate(new SPIRVMemberDecorate(Kind, MemberNumber, this, Literal));
319}
320
321void
322SPIRVEntry::eraseMemberDecorate(SPIRVWord MemberNumber, Decoration Dec){
323  MemberDecorates.erase(std::make_pair(MemberNumber, Dec));
324}
325
326void
327SPIRVEntry::takeMemberDecorates(SPIRVEntry *E){
328  MemberDecorates = std::move(E->MemberDecorates);
329  SPIRVDBG(spvdbgs() << "[takeMemberDecorates] " << Id << '\n';)
330}
331
332void
333SPIRVEntry::takeAnnotations(SPIRVForward *E){
334  Module->setName(this, E->getName());
335  takeDecorates(E);
336  takeMemberDecorates(E);
337  takeLine(E);
338  if (OpCode == OpFunction)
339    static_cast<SPIRVFunction *>(this)->takeExecutionModes(E);
340}
341
342// Check if an entry has Kind of decoration and get the literal of the
343// first decoration of such kind at Index.
344bool
345SPIRVEntry::hasDecorate(Decoration Kind, size_t Index, SPIRVWord *Result)const {
346  DecorateMapType::const_iterator Loc = Decorates.find(Kind);
347  if (Loc == Decorates.end())
348    return false;
349  if (Result)
350    *Result = Loc->second->getLiteral(Index);
351  return true;
352}
353
354// Get literals of all decorations of Kind at Index.
355std::set<SPIRVWord>
356SPIRVEntry::getDecorate(Decoration Kind, size_t Index) const {
357  auto Range = Decorates.equal_range(Kind);
358  std::set<SPIRVWord> Value;
359  for (auto I = Range.first, E = Range.second; I != E; ++I) {
360    assert(Index < I->second->getLiteralCount() && "Invalid index");
361    Value.insert(I->second->getLiteral(Index));
362  }
363  return Value;
364}
365
366bool
367SPIRVEntry::hasLinkageType() const {
368  return OpCode == OpFunction || OpCode == OpVariable;
369}
370
371void
372SPIRVEntry::encodeDecorate(spv_ostream &O) const {
373  for (auto& i:Decorates)
374    O << *i.second;
375}
376
377SPIRVLinkageTypeKind
378SPIRVEntry::getLinkageType() const {
379  assert(hasLinkageType());
380  DecorateMapType::const_iterator Loc = Decorates.find(DecorationLinkageAttributes);
381  if (Loc == Decorates.end())
382    return LinkageTypeInternal;
383  return static_cast<const SPIRVDecorateLinkageAttr*>(Loc->second)->getLinkageType();
384}
385
386void
387SPIRVEntry::setLinkageType(SPIRVLinkageTypeKind LT) {
388  assert(isValid(LT));
389  assert(hasLinkageType());
390  addDecorate(new SPIRVDecorateLinkageAttr(this, Name, LT));
391}
392
393void
394SPIRVEntry::updateModuleVersion() const {
395  if (!Module)
396    return;
397
398  Module->setMinSPIRVVersion(getRequiredSPIRVVersion());
399}
400
401spv_ostream &
402operator<<(spv_ostream &O, const SPIRVEntry &E) {
403  E.validate();
404  E.encodeAll(O);
405  O << SPIRVNL();
406  return O;
407}
408
409std::istream &
410operator>>(std::istream &I, SPIRVEntry &E) {
411  E.decode(I);
412  return I;
413}
414
415SPIRVEntryPoint::SPIRVEntryPoint(SPIRVModule *TheModule,
416  SPIRVExecutionModelKind TheExecModel, SPIRVId TheId,
417  const std::string &TheName)
418  :SPIRVAnnotation(TheModule->get<SPIRVFunction>(TheId),
419   getSizeInWords(TheName) + 3), ExecModel(TheExecModel), Name(TheName){
420}
421
422void
423SPIRVEntryPoint::encode(spv_ostream &O) const {
424  getEncoder(O) << ExecModel << Target << Name;
425}
426
427void
428SPIRVEntryPoint::decode(std::istream &I) {
429  getDecoder(I) >> ExecModel >> Target >> Name;
430  Module->setName(getOrCreateTarget(), Name);
431  Module->addEntryPoint(ExecModel, Target);
432}
433
434void
435SPIRVExecutionMode::encode(spv_ostream &O) const {
436  getEncoder(O) << Target << ExecMode << WordLiterals;
437}
438
439void
440SPIRVExecutionMode::decode(std::istream &I) {
441  getDecoder(I) >> Target >> ExecMode;
442  switch(ExecMode) {
443  case ExecutionModeLocalSize:
444  case ExecutionModeLocalSizeHint:
445    WordLiterals.resize(3);
446    break;
447  case ExecutionModeInvocations:
448  case ExecutionModeOutputVertices:
449  case ExecutionModeVecTypeHint:
450    WordLiterals.resize(1);
451    break;
452  default:
453    // Do nothing. Keep this to avoid VS2013 warning.
454    break;
455  }
456  getDecoder(I) >> WordLiterals;
457  getOrCreateTarget()->addExecutionMode(this);
458}
459
460SPIRVForward *
461SPIRVAnnotationGeneric::getOrCreateTarget()const {
462  SPIRVEntry *Entry = nullptr;
463  bool Found = Module->exist(Target, &Entry);
464  assert((!Found || Entry->getOpCode() == OpForward) &&
465      "Annotations only allowed on forward");
466  if (!Found)
467    Entry = Module->addForward(Target, nullptr);
468  return static_cast<SPIRVForward *>(Entry);
469}
470
471SPIRVName::SPIRVName(const SPIRVEntry *TheTarget, const std::string& TheStr)
472  :SPIRVAnnotation(TheTarget, getSizeInWords(TheStr) + 2), Str(TheStr){
473}
474
475void
476SPIRVName::encode(spv_ostream &O) const {
477  getEncoder(O) << Target << Str;
478}
479
480void
481SPIRVName::decode(std::istream &I) {
482  getDecoder(I) >> Target >> Str;
483  Module->setName(getOrCreateTarget(), Str);
484}
485
486void
487SPIRVName::validate() const {
488  assert(WordCount == getSizeInWords(Str) + 2 && "Incorrect word count");
489}
490
491_SPIRV_IMP_ENCDEC2(SPIRVString, Id, Str)
492_SPIRV_IMP_ENCDEC3(SPIRVMemberName, Target, MemberNumber, Str)
493
494void
495SPIRVLine::encode(spv_ostream &O) const {
496  getEncoder(O) << Target << FileName << Line << Column;
497}
498
499void
500SPIRVLine::decode(std::istream &I) {
501  getDecoder(I) >> Target >> FileName >> Line >> Column;
502  Module->addLine(getOrCreateTarget(), get<SPIRVString>(FileName), Line, Column);
503}
504
505void
506SPIRVLine::validate() const {
507  assert(OpCode == OpLine);
508  assert(WordCount == 5);
509  assert(get<SPIRVEntry>(Target));
510  assert(get<SPIRVEntry>(FileName)->getOpCode() == OpString);
511  assert(Line != SPIRVWORD_MAX);
512  assert(Column != SPIRVWORD_MAX);
513}
514
515void
516SPIRVMemberName::validate() const {
517  assert(OpCode == OpMemberName);
518  assert(WordCount == getSizeInWords(Str) + FixedWC);
519  assert(get<SPIRVEntry>(Target)->getOpCode() == OpTypeStruct);
520  assert(MemberNumber < get<SPIRVTypeStruct>(Target)->getStructMemberCount());
521}
522
523SPIRVExtInstImport::SPIRVExtInstImport(SPIRVModule *TheModule, SPIRVId TheId,
524    const std::string &TheStr):
525  SPIRVEntry(TheModule, 2 + getSizeInWords(TheStr), OC, TheId), Str(TheStr){
526  validate();
527}
528
529void
530SPIRVExtInstImport::encode(spv_ostream &O) const {
531  getEncoder(O) << Id << Str;
532}
533
534void
535SPIRVExtInstImport::decode(std::istream &I) {
536  getDecoder(I) >> Id >> Str;
537  Module->importBuiltinSetWithId(Str, Id);
538}
539
540void
541SPIRVExtInstImport::validate() const {
542  SPIRVEntry::validate();
543  assert(!Str.empty() && "Invalid builtin set");
544}
545
546void
547SPIRVMemoryModel::encode(spv_ostream &O) const {
548  getEncoder(O) << Module->getAddressingModel() <<
549      Module->getMemoryModel();
550}
551
552void
553SPIRVMemoryModel::decode(std::istream &I) {
554  SPIRVAddressingModelKind AddrModel;
555  SPIRVMemoryModelKind MemModel;
556  getDecoder(I) >> AddrModel >> MemModel;
557  Module->setAddressingModel(AddrModel);
558  Module->setMemoryModel(MemModel);
559}
560
561void
562SPIRVMemoryModel::validate() const {
563  auto AM = Module->getAddressingModel();
564  auto MM = Module->getMemoryModel();
565  SPIRVCK(isValid(AM), InvalidAddressingModel, "Actual is "+AM );
566  SPIRVCK(isValid(MM), InvalidMemoryModel, "Actual is "+MM);
567}
568
569void
570SPIRVSource::encode(spv_ostream &O) const {
571  SPIRVWord Ver = SPIRVWORD_MAX;
572  auto Language = Module->getSourceLanguage(&Ver);
573  getEncoder(O) << Language << Ver;
574}
575
576void
577SPIRVSource::decode(std::istream &I) {
578  SourceLanguage Lang = SourceLanguageUnknown;
579  SPIRVWord Ver = SPIRVWORD_MAX;
580  getDecoder(I) >> Lang >> Ver;
581  Module->setSourceLanguage(Lang, Ver);
582}
583
584SPIRVSourceExtension::SPIRVSourceExtension(SPIRVModule *M,
585    const std::string &SS)
586  :SPIRVEntryNoId(M, 1 + getSizeInWords(SS)), S(SS){}
587
588void
589SPIRVSourceExtension::encode(spv_ostream &O) const {
590  getEncoder(O) << S;
591}
592
593void
594SPIRVSourceExtension::decode(std::istream &I) {
595  getDecoder(I) >> S;
596  Module->getSourceExtension().insert(S);
597}
598
599SPIRVExtension::SPIRVExtension(SPIRVModule *M, const std::string &SS)
600  :SPIRVEntryNoId(M, 1 + getSizeInWords(SS)), S(SS){}
601
602void
603SPIRVExtension::encode(spv_ostream &O) const {
604  getEncoder(O) << S;
605}
606
607void
608SPIRVExtension::decode(std::istream &I) {
609  getDecoder(I) >> S;
610  Module->getExtension().insert(S);
611}
612
613SPIRVCapability::SPIRVCapability(SPIRVModule *M, SPIRVCapabilityKind K)
614  :SPIRVEntryNoId(M, 2), Kind(K){
615  updateModuleVersion();
616}
617
618void
619SPIRVCapability::encode(spv_ostream &O) const {
620  getEncoder(O) << Kind;
621}
622
623void
624SPIRVCapability::decode(std::istream &I) {
625  getDecoder(I) >> Kind;
626  Module->addCapability(Kind);
627}
628
629} // namespace SPIRV
630
631