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 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 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 71 SPIRVFunction::getDecoder(std::istream &IS) { 72 return SPIRVDecoder(IS, *this); 73 } 74 75 void 76 SPIRVFunction::encode(spv_ostream &O) const { 77 getEncoder(O) << Type << Id << FCtrlMask << FuncType; 78 } 79 80 void 81 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 92 SPIRVFunction::encodeExecutionModes(spv_ostream &O)const { 93 for (auto &I:ExecModes) 94 O << *I.second; 95 } 96 97 void 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 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 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