• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
56 using namespace SPIRV;
57 
58 namespace SPIRV{
59 
60 template<typename T>
create()61 SPIRVEntry* create() {
62   return new T();
63 }
64 
65 SPIRVEntry *
create(Op OpCode)66 SPIRVEntry::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 
95 std::unique_ptr<SPIRV::SPIRVEntry>
create_unique(Op OC)96 SPIRVEntry::create_unique(Op OC) {
97   return std::unique_ptr<SPIRVEntry>(create(OC));
98 }
99 
100 std::unique_ptr<SPIRV::SPIRVExtInst>
create_unique(SPIRVExtInstSetKind Set,unsigned ExtOp)101 SPIRVEntry::create_unique(SPIRVExtInstSetKind Set,
102     unsigned ExtOp) {
103   return std::unique_ptr<SPIRVExtInst>(new SPIRVExtInst(Set, ExtOp));
104 }
105 
106 SPIRVErrorLog &
getErrorLog() const107 SPIRVEntry::getErrorLog()const {
108   return Module->getErrorLog();
109 }
110 
111 bool
exist(SPIRVId TheId) const112 SPIRVEntry::exist(SPIRVId TheId)const {
113   return Module->exist(TheId);
114 }
115 
116 SPIRVEntry *
getOrCreate(SPIRVId TheId) const117 SPIRVEntry::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 
125 SPIRVValue *
getValue(SPIRVId TheId) const126 SPIRVEntry::getValue(SPIRVId TheId)const {
127   return get<SPIRVValue>(TheId);
128 }
129 
130 SPIRVType *
getValueType(SPIRVId TheId) const131 SPIRVEntry::getValueType(SPIRVId TheId)const {
132   return get<SPIRVValue>(TheId)->getType();
133 }
134 
135 SPIRVEncoder
getEncoder(spv_ostream & O) const136 SPIRVEntry::getEncoder(spv_ostream &O)const{
137   return SPIRVEncoder(O);
138 }
139 
140 SPIRVDecoder
getDecoder(std::istream & I)141 SPIRVEntry::getDecoder(std::istream& I){
142   return SPIRVDecoder(I, *Module);
143 }
144 
145 void
setWordCount(SPIRVWord TheWordCount)146 SPIRVEntry::setWordCount(SPIRVWord TheWordCount){
147   WordCount = TheWordCount;
148 }
149 
150 void
setName(const std::string & TheName)151 SPIRVEntry::setName(const std::string& TheName) {
152   Name = TheName;
153   SPIRVDBG(spvdbgs() << "Set name for obj " << Id << " " <<
154     Name << '\n');
155 }
156 
157 void
setModule(SPIRVModule * TheModule)158 SPIRVEntry::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 
166 void
encode(spv_ostream & O) const167 SPIRVEntry::encode(spv_ostream &O) const {
168   assert (0 && "Not implemented");
169 }
170 
171 void
encodeName(spv_ostream & O) const172 SPIRVEntry::encodeName(spv_ostream &O) const {
173   if (!Name.empty())
174     O << SPIRVName(this, Name);
175 }
176 
177 void
encodeAll(spv_ostream & O) const178 SPIRVEntry::encodeAll(spv_ostream &O) const {
179   encodeWordCountOpCode(O);
180   encode(O);
181   encodeChildren(O);
182 }
183 
184 void
encodeChildren(spv_ostream & O) const185 SPIRVEntry::encodeChildren(spv_ostream &O)const {
186 }
187 
188 void
encodeWordCountOpCode(spv_ostream & O) const189 SPIRVEntry::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.
202 void
decode(std::istream & I)203 SPIRVEntry::decode(std::istream &I) {
204   assert (0 && "Not implemented");
205 }
206 
207 std::vector<SPIRVValue *>
getValues(const std::vector<SPIRVId> & IdVec) const208 SPIRVEntry::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 
215 std::vector<SPIRVType *>
getValueTypes(const std::vector<SPIRVId> & IdVec) const216 SPIRVEntry::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 
223 std::vector<SPIRVId>
getIds(const std::vector<SPIRVValue * > ValueVec) const224 SPIRVEntry::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 
231 SPIRVEntry *
getEntry(SPIRVId TheId) const232 SPIRVEntry::getEntry(SPIRVId TheId) const {
233   return Module->getEntry(TheId);
234 }
235 
236 void
validateFunctionControlMask(SPIRVWord TheFCtlMask) const237 SPIRVEntry::validateFunctionControlMask(SPIRVWord TheFCtlMask)
238   const {
239   SPIRVCK(isValidFunctionControlMask(TheFCtlMask),
240       InvalidFunctionControlMask, "");
241 }
242 
243 void
validateValues(const std::vector<SPIRVId> & Ids) const244 SPIRVEntry::validateValues(const std::vector<SPIRVId> &Ids)const {
245   for (auto I:Ids)
246     getValue(I)->validate();
247 }
248 
249 void
validateBuiltin(SPIRVWord TheSet,SPIRVWord Index) const250 SPIRVEntry::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 
257 void
addDecorate(const SPIRVDecorate * Dec)258 SPIRVEntry::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 
264 void
addDecorate(Decoration Kind)265 SPIRVEntry::addDecorate(Decoration Kind) {
266   addDecorate(new SPIRVDecorate(Kind, this));
267 }
268 
269 void
addDecorate(Decoration Kind,SPIRVWord Literal)270 SPIRVEntry::addDecorate(Decoration Kind, SPIRVWord Literal) {
271   addDecorate(new SPIRVDecorate(Kind, this, Literal));
272 }
273 
274 void
eraseDecorate(Decoration Dec)275 SPIRVEntry::eraseDecorate(Decoration Dec){
276   Decorates.erase(Dec);
277 }
278 
279 void
takeDecorates(SPIRVEntry * E)280 SPIRVEntry::takeDecorates(SPIRVEntry *E){
281   Decorates = std::move(E->Decorates);
282   SPIRVDBG(spvdbgs() << "[takeDecorates] " << Id << '\n';)
283 }
284 
285 void
setLine(SPIRVLine * L)286 SPIRVEntry::setLine(SPIRVLine *L){
287   Line = L;
288   L->setTargetId(Id);
289   SPIRVDBG(spvdbgs() << "[setLine] " << *L << '\n';)
290 }
291 
292 void
takeLine(SPIRVEntry * E)293 SPIRVEntry::takeLine(SPIRVEntry *E){
294   Line = E->Line;
295   if (Line == nullptr)
296     return;
297   Line->setTargetId(Id);
298   E->Line = nullptr;
299 }
300 
301 void
addMemberDecorate(const SPIRVMemberDecorate * Dec)302 SPIRVEntry::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 
310 void
addMemberDecorate(SPIRVWord MemberNumber,Decoration Kind)311 SPIRVEntry::addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind) {
312   addMemberDecorate(new SPIRVMemberDecorate(Kind, MemberNumber, this));
313 }
314 
315 void
addMemberDecorate(SPIRVWord MemberNumber,Decoration Kind,SPIRVWord Literal)316 SPIRVEntry::addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind,
317     SPIRVWord Literal) {
318   addMemberDecorate(new SPIRVMemberDecorate(Kind, MemberNumber, this, Literal));
319 }
320 
321 void
eraseMemberDecorate(SPIRVWord MemberNumber,Decoration Dec)322 SPIRVEntry::eraseMemberDecorate(SPIRVWord MemberNumber, Decoration Dec){
323   MemberDecorates.erase(std::make_pair(MemberNumber, Dec));
324 }
325 
326 void
takeMemberDecorates(SPIRVEntry * E)327 SPIRVEntry::takeMemberDecorates(SPIRVEntry *E){
328   MemberDecorates = std::move(E->MemberDecorates);
329   SPIRVDBG(spvdbgs() << "[takeMemberDecorates] " << Id << '\n';)
330 }
331 
332 void
takeAnnotations(SPIRVForward * E)333 SPIRVEntry::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.
344 bool
hasDecorate(Decoration Kind,size_t Index,SPIRVWord * Result) const345 SPIRVEntry::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.
355 std::set<SPIRVWord>
getDecorate(Decoration Kind,size_t Index) const356 SPIRVEntry::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 
366 bool
hasLinkageType() const367 SPIRVEntry::hasLinkageType() const {
368   return OpCode == OpFunction || OpCode == OpVariable;
369 }
370 
371 void
encodeDecorate(spv_ostream & O) const372 SPIRVEntry::encodeDecorate(spv_ostream &O) const {
373   for (auto& i:Decorates)
374     O << *i.second;
375 }
376 
377 SPIRVLinkageTypeKind
getLinkageType() const378 SPIRVEntry::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 
386 void
setLinkageType(SPIRVLinkageTypeKind LT)387 SPIRVEntry::setLinkageType(SPIRVLinkageTypeKind LT) {
388   assert(isValid(LT));
389   assert(hasLinkageType());
390   addDecorate(new SPIRVDecorateLinkageAttr(this, Name, LT));
391 }
392 
393 void
updateModuleVersion() const394 SPIRVEntry::updateModuleVersion() const {
395   if (!Module)
396     return;
397 
398   Module->setMinSPIRVVersion(getRequiredSPIRVVersion());
399 }
400 
401 spv_ostream &
operator <<(spv_ostream & O,const SPIRVEntry & E)402 operator<<(spv_ostream &O, const SPIRVEntry &E) {
403   E.validate();
404   E.encodeAll(O);
405   O << SPIRVNL();
406   return O;
407 }
408 
409 std::istream &
operator >>(std::istream & I,SPIRVEntry & E)410 operator>>(std::istream &I, SPIRVEntry &E) {
411   E.decode(I);
412   return I;
413 }
414 
SPIRVEntryPoint(SPIRVModule * TheModule,SPIRVExecutionModelKind TheExecModel,SPIRVId TheId,const std::string & TheName)415 SPIRVEntryPoint::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 
422 void
encode(spv_ostream & O) const423 SPIRVEntryPoint::encode(spv_ostream &O) const {
424   getEncoder(O) << ExecModel << Target << Name;
425 }
426 
427 void
decode(std::istream & I)428 SPIRVEntryPoint::decode(std::istream &I) {
429   getDecoder(I) >> ExecModel >> Target >> Name;
430   Module->setName(getOrCreateTarget(), Name);
431   Module->addEntryPoint(ExecModel, Target);
432 }
433 
434 void
encode(spv_ostream & O) const435 SPIRVExecutionMode::encode(spv_ostream &O) const {
436   getEncoder(O) << Target << ExecMode << WordLiterals;
437 }
438 
439 void
decode(std::istream & I)440 SPIRVExecutionMode::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 
460 SPIRVForward *
getOrCreateTarget() const461 SPIRVAnnotationGeneric::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 
SPIRVName(const SPIRVEntry * TheTarget,const std::string & TheStr)471 SPIRVName::SPIRVName(const SPIRVEntry *TheTarget, const std::string& TheStr)
472   :SPIRVAnnotation(TheTarget, getSizeInWords(TheStr) + 2), Str(TheStr){
473 }
474 
475 void
encode(spv_ostream & O) const476 SPIRVName::encode(spv_ostream &O) const {
477   getEncoder(O) << Target << Str;
478 }
479 
480 void
decode(std::istream & I)481 SPIRVName::decode(std::istream &I) {
482   getDecoder(I) >> Target >> Str;
483   Module->setName(getOrCreateTarget(), Str);
484 }
485 
486 void
validate() const487 SPIRVName::validate() const {
488   assert(WordCount == getSizeInWords(Str) + 2 && "Incorrect word count");
489 }
490 
_SPIRV_IMP_ENCDEC2(SPIRVString,Id,Str)491 _SPIRV_IMP_ENCDEC2(SPIRVString, Id, Str)
492 _SPIRV_IMP_ENCDEC3(SPIRVMemberName, Target, MemberNumber, Str)
493 
494 void
495 SPIRVLine::encode(spv_ostream &O) const {
496   getEncoder(O) << Target << FileName << Line << Column;
497 }
498 
499 void
decode(std::istream & I)500 SPIRVLine::decode(std::istream &I) {
501   getDecoder(I) >> Target >> FileName >> Line >> Column;
502   Module->addLine(getOrCreateTarget(), get<SPIRVString>(FileName), Line, Column);
503 }
504 
505 void
validate() const506 SPIRVLine::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 
515 void
validate() const516 SPIRVMemberName::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 
SPIRVExtInstImport(SPIRVModule * TheModule,SPIRVId TheId,const std::string & TheStr)523 SPIRVExtInstImport::SPIRVExtInstImport(SPIRVModule *TheModule, SPIRVId TheId,
524     const std::string &TheStr):
525   SPIRVEntry(TheModule, 2 + getSizeInWords(TheStr), OC, TheId), Str(TheStr){
526   validate();
527 }
528 
529 void
encode(spv_ostream & O) const530 SPIRVExtInstImport::encode(spv_ostream &O) const {
531   getEncoder(O) << Id << Str;
532 }
533 
534 void
decode(std::istream & I)535 SPIRVExtInstImport::decode(std::istream &I) {
536   getDecoder(I) >> Id >> Str;
537   Module->importBuiltinSetWithId(Str, Id);
538 }
539 
540 void
validate() const541 SPIRVExtInstImport::validate() const {
542   SPIRVEntry::validate();
543   assert(!Str.empty() && "Invalid builtin set");
544 }
545 
546 void
encode(spv_ostream & O) const547 SPIRVMemoryModel::encode(spv_ostream &O) const {
548   getEncoder(O) << Module->getAddressingModel() <<
549       Module->getMemoryModel();
550 }
551 
552 void
decode(std::istream & I)553 SPIRVMemoryModel::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 
561 void
validate() const562 SPIRVMemoryModel::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 
569 void
encode(spv_ostream & O) const570 SPIRVSource::encode(spv_ostream &O) const {
571   SPIRVWord Ver = SPIRVWORD_MAX;
572   auto Language = Module->getSourceLanguage(&Ver);
573   getEncoder(O) << Language << Ver;
574 }
575 
576 void
decode(std::istream & I)577 SPIRVSource::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 
SPIRVSourceExtension(SPIRVModule * M,const std::string & SS)584 SPIRVSourceExtension::SPIRVSourceExtension(SPIRVModule *M,
585     const std::string &SS)
586   :SPIRVEntryNoId(M, 1 + getSizeInWords(SS)), S(SS){}
587 
588 void
encode(spv_ostream & O) const589 SPIRVSourceExtension::encode(spv_ostream &O) const {
590   getEncoder(O) << S;
591 }
592 
593 void
decode(std::istream & I)594 SPIRVSourceExtension::decode(std::istream &I) {
595   getDecoder(I) >> S;
596   Module->getSourceExtension().insert(S);
597 }
598 
SPIRVExtension(SPIRVModule * M,const std::string & SS)599 SPIRVExtension::SPIRVExtension(SPIRVModule *M, const std::string &SS)
600   :SPIRVEntryNoId(M, 1 + getSizeInWords(SS)), S(SS){}
601 
602 void
encode(spv_ostream & O) const603 SPIRVExtension::encode(spv_ostream &O) const {
604   getEncoder(O) << S;
605 }
606 
607 void
decode(std::istream & I)608 SPIRVExtension::decode(std::istream &I) {
609   getDecoder(I) >> S;
610   Module->getExtension().insert(S);
611 }
612 
SPIRVCapability(SPIRVModule * M,SPIRVCapabilityKind K)613 SPIRVCapability::SPIRVCapability(SPIRVModule *M, SPIRVCapabilityKind K)
614   :SPIRVEntryNoId(M, 2), Kind(K){
615   updateModuleVersion();
616 }
617 
618 void
encode(spv_ostream & O) const619 SPIRVCapability::encode(spv_ostream &O) const {
620   getEncoder(O) << Kind;
621 }
622 
623 void
decode(std::istream & I)624 SPIRVCapability::decode(std::istream &I) {
625   getDecoder(I) >> Kind;
626   Module->addCapability(Kind);
627 }
628 
629 } // namespace SPIRV
630 
631