• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- SPIRVFunction.cpp � Class to represent a SPIR-V Function --*- 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 //===----------------------------------------------------------------------===//
9 //
10 // This file implements Function class for SPIRV.
11 //
12 // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved.
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal with the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // Redistributions of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimers.
23 // Redistributions in binary form must reproduce the above copyright notice,
24 // this list of conditions and the following disclaimers in the documentation
25 // and/or other materials provided with the distribution.
26 // Neither the names of Advanced Micro Devices, Inc., nor the names of its
27 // contributors may be used to endorse or promote products derived from this
28 // Software without specific prior written permission.
29 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
35 // THE SOFTWARE.
36 //
37 //===----------------------------------------------------------------------===//
38 
39 #include "SPIRVEntry.h"
40 #include "SPIRVFunction.h"
41 #include "SPIRVBasicBlock.h"
42 #include "SPIRVInstruction.h"
43 #include "SPIRVStream.h"
44 
45 #include <functional>
46 #include <algorithm>
47 using namespace SPIRV;
48 
SPIRVFunctionParameter(SPIRVType * TheType,SPIRVId TheId,SPIRVFunction * TheParent,unsigned TheArgNo)49 SPIRVFunctionParameter::SPIRVFunctionParameter(SPIRVType *TheType, SPIRVId TheId,
50     SPIRVFunction *TheParent, unsigned TheArgNo):
51         SPIRVValue(TheParent->getModule(), 3, OpFunctionParameter,
52         TheType, TheId),
53     ParentFunc(TheParent),
54     ArgNo(TheArgNo){
55   validate();
56 }
57 
58 void
foreachAttr(std::function<void (SPIRVFuncParamAttrKind)> Func)59 SPIRVFunctionParameter::foreachAttr(
60     std::function<void(SPIRVFuncParamAttrKind)>Func){
61   auto Locs = Decorates.equal_range(DecorationFuncParamAttr);
62   for (auto I = Locs.first, E = Locs.second; I != E; ++I){
63     auto Attr = static_cast<SPIRVFuncParamAttrKind>(
64         I->second->getLiteral(0));
65     assert(isValid(Attr));
66     Func(Attr);
67   }
68 }
69 
70 SPIRVDecoder
getDecoder(std::istream & IS)71 SPIRVFunction::getDecoder(std::istream &IS) {
72   return SPIRVDecoder(IS, *this);
73 }
74 
75 void
encode(spv_ostream & O) const76 SPIRVFunction::encode(spv_ostream &O) const {
77   getEncoder(O) << Type << Id << FCtrlMask << FuncType;
78 }
79 
80 void
encodeChildren(spv_ostream & O) const81 SPIRVFunction::encodeChildren(spv_ostream &O) const {
82   O << SPIRVNL();
83   for (auto &I:Parameters)
84     O << *I;
85   O << SPIRVNL();
86   for (auto &I:BBVec)
87     O << *I;
88   O << SPIRVFunctionEnd();
89 }
90 
91 void
encodeExecutionModes(spv_ostream & O) const92 SPIRVFunction::encodeExecutionModes(spv_ostream &O)const {
93   for (auto &I:ExecModes)
94     O << *I.second;
95 }
96 
97 void
decode(std::istream & I)98 SPIRVFunction::decode(std::istream &I) {
99   SPIRVDecoder Decoder = getDecoder(I);
100   Decoder >> Type >> Id >> FCtrlMask >> FuncType;
101   Module->addFunction(this);
102   SPIRVDBG(spvdbgs() << "Decode function: " << Id << '\n');
103 
104   Decoder.getWordCountAndOpCode();
105   while (!I.eof()) {
106     if (Decoder.OpCode == OpFunctionEnd)
107       break;
108 
109     switch(Decoder.OpCode) {
110     case OpFunctionParameter: {
111       auto Param = static_cast<SPIRVFunctionParameter *>(Decoder.getEntry());
112       assert(Param);
113       Param->setParent(this);
114       Parameters.push_back(Param);
115       Decoder.getWordCountAndOpCode();
116       continue;
117       break;
118     }
119     case OpLabel: {
120       decodeBB(Decoder);
121       break;
122     }
123     default:
124       assert (0 && "Invalid SPIRV format");
125     }
126   }
127 }
128 
129 /// Decode basic block and contained instructions.
130 /// Do it here instead of in BB:decode to avoid back track in input stream.
131 void
decodeBB(SPIRVDecoder & Decoder)132 SPIRVFunction::decodeBB(SPIRVDecoder &Decoder) {
133   SPIRVBasicBlock *BB = static_cast<SPIRVBasicBlock*>(Decoder.getEntry());
134   assert(BB);
135   addBasicBlock(BB);
136   SPIRVDBG(spvdbgs() << "Decode BB: " << BB->getId() << '\n');
137 
138   Decoder.setScope(BB);
139   while(Decoder.getWordCountAndOpCode()) {
140     if (Decoder.OpCode == OpFunctionEnd ||
141         Decoder.OpCode == OpLabel) {
142       break;
143     }
144 
145     if (Decoder.OpCode == OpName ||
146         Decoder.OpCode == OpDecorate) {
147       Decoder.getEntry();
148       continue;
149     }
150 
151     SPIRVInstruction *Inst = static_cast<SPIRVInstruction *>(Decoder.getEntry());
152     assert(Inst);
153     BB->addInstruction(Inst);
154   }
155   Decoder.setScope(this);
156 }
157 
158 void
foreachReturnValueAttr(std::function<void (SPIRVFuncParamAttrKind)> Func)159 SPIRVFunction::foreachReturnValueAttr(
160     std::function<void(SPIRVFuncParamAttrKind)>Func){
161   auto Locs = Decorates.equal_range(DecorationFuncParamAttr);
162   for (auto I = Locs.first, E = Locs.second; I != E; ++I){
163     auto Attr = static_cast<SPIRVFuncParamAttrKind>(
164         I->second->getLiteral(0));
165     assert(isValid(Attr));
166     Func(Attr);
167   }
168 }
169