1 /*========================== begin_copyright_notice ============================ 2 3 Copyright (C) 2017-2021 Intel Corporation 4 5 SPDX-License-Identifier: MIT 6 7 ============================= end_copyright_notice ===========================*/ 8 9 /*========================== begin_copyright_notice ============================ 10 11 This file is distributed under the University of Illinois Open Source License. 12 See LICENSE.TXT for details. 13 14 ============================= end_copyright_notice ===========================*/ 15 16 /*========================== begin_copyright_notice ============================ 17 18 Copyright (C) 2014 Advanced Micro Devices, Inc. All rights reserved. 19 20 Permission is hereby granted, free of charge, to any person obtaining a 21 copy of this software and associated documentation files (the "Software"), 22 to deal with the Software without restriction, including without limitation 23 the rights to use, copy, modify, merge, publish, distribute, sublicense, 24 and/or sell copies of the Software, and to permit persons to whom the 25 Software is furnished to do so, subject to the following conditions: 26 27 Redistributions of source code must retain the above copyright notice, 28 this list of conditions and the following disclaimers. 29 Redistributions in binary form must reproduce the above copyright notice, 30 this list of conditions and the following disclaimers in the documentation 31 and/or other materials provided with the distribution. 32 Neither the names of Advanced Micro Devices, Inc., nor the names of its 33 contributors may be used to endorse or promote products derived from this 34 Software without specific prior written permission. 35 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 36 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 37 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 38 CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 39 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 40 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 41 THE SOFTWARE. 42 43 ============================= end_copyright_notice ===========================*/ 44 45 // This file defines the values defined in SPIR-V spec with op codes. 46 // The name of the SPIR-V values follow the op code name in the spec. 47 // This is for readability and ease of using macro to handle types. 48 49 #ifndef SPIRVVALUE_HPP_ 50 #define SPIRVVALUE_HPP_ 51 52 #include "SPIRVEntry.h" 53 #include "SPIRVType.h" 54 #include "SPIRVDecorate.h" 55 #include "Probe/Assertion.h" 56 57 #include <iostream> 58 #include <map> 59 #include <memory> 60 61 namespace igc_spv{ 62 63 class SPIRVValue: public SPIRVEntry { 64 public: 65 // Complete constructor for value with id and type SPIRVValue(SPIRVModule * M,unsigned TheWordCount,Op TheOpCode,SPIRVType * TheType,SPIRVId TheId)66 SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode, 67 SPIRVType *TheType, SPIRVId TheId) 68 :SPIRVEntry(M, TheWordCount, TheOpCode, TheId), Type(TheType) { 69 validate(); 70 } 71 // Complete constructor for value with type but without id SPIRVValue(SPIRVModule * M,unsigned TheWordCount,Op TheOpCode,SPIRVType * TheType)72 SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode, 73 SPIRVType *TheType) 74 :SPIRVEntry(M, TheWordCount, TheOpCode), Type(TheType) { 75 setHasNoId(); 76 validate(); 77 } 78 // Complete constructor for value with id but without type SPIRVValue(SPIRVModule * M,unsigned TheWordCount,Op TheOpCode,SPIRVId TheId)79 SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode, 80 SPIRVId TheId) 81 :SPIRVEntry(M, TheWordCount, TheOpCode, TheId), Type(NULL) { 82 setHasNoType(); 83 validate(); 84 } 85 // Complete constructor for value without id and type SPIRVValue(SPIRVModule * M,unsigned TheWordCount,Op TheOpCode)86 SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode) 87 :SPIRVEntry(M, TheWordCount, TheOpCode), Type(NULL) { 88 setHasNoId(); 89 setHasNoType(); 90 validate(); 91 } 92 // Incomplete constructor SPIRVValue(Op TheOpCode)93 SPIRVValue(Op TheOpCode):SPIRVEntry(TheOpCode), Type(NULL) {} 94 hasType()95 bool hasType()const { return !(Attrib & SPIRVEA_NOTYPE);} getType()96 SPIRVType *getType()const { 97 IGC_ASSERT_MESSAGE(hasType(), "value has no type"); 98 return Type; 99 } 100 bool isVolatile()const; 101 bool hasAlignment(SPIRVWord *Result=0)const; 102 bool hasNoSignedWrap() const; 103 bool hasNoUnsignedWrap() const; 104 105 void setAlignment(SPIRVWord); 106 void setVolatile(bool IsVolatile); 107 void setNoSignedWrap(bool HasNoSignedWrap); 108 void setNoUnsignedWrap(bool HasNoUnsignedWrap); 109 validate()110 void validate()const { 111 SPIRVEntry::validate(); 112 IGC_ASSERT_MESSAGE((!hasType() || Type), "Invalid type"); 113 } 114 setType(SPIRVType * Ty)115 void setType(SPIRVType *Ty) { 116 Type = Ty; 117 IGC_ASSERT(!Ty || !Ty->isTypeVoid() || OpCode == OpFunction); 118 if (Ty && (!Ty->isTypeVoid() || OpCode == OpFunction)) 119 setHasType(); 120 else 121 setHasNoType(); 122 } 123 getRequiredCapability()124 CapVec getRequiredCapability() const { 125 CapVec CV; 126 if (!hasType()) 127 return CV; 128 if (Type->isTypeFloat(16)) 129 CV.push_back(SPIRVCapabilityKind::CapabilityFloat16); 130 else if (Type->isTypeFloat(64)) 131 CV.push_back(SPIRVCapabilityKind::CapabilityFloat64); 132 else if (Type->isTypeInt(16)) 133 CV.push_back(SPIRVCapabilityKind::CapabilityInt16); 134 else if (Type->isTypeInt(64)) 135 CV.push_back(SPIRVCapabilityKind::CapabilityInt64); 136 return CV; 137 } 138 139 protected: setHasNoType()140 void setHasNoType() { Attrib |= SPIRVEA_NOTYPE;} setHasType()141 void setHasType() { Attrib &= ~SPIRVEA_NOTYPE;} 142 143 SPIRVType *Type; // Value Type 144 }; 145 146 template<Op OC> 147 class SPIRVConstantBase: public SPIRVValue { 148 public: 149 // Complete constructor for integer constant SPIRVConstantBase(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId,uint64_t TheValue)150 SPIRVConstantBase(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId, 151 uint64_t TheValue) 152 :SPIRVValue(M, 0, OC, TheType, TheId){ 153 Union.UInt64Val = TheValue; 154 recalculateWordCount(); 155 validate(); 156 } 157 // Complete constructor for float constant SPIRVConstantBase(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId,float TheValue)158 SPIRVConstantBase(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId, float TheValue) 159 :SPIRVValue(M, 0, OC, TheType, TheId){ 160 Union.FloatVal = TheValue; 161 recalculateWordCount(); 162 validate(); 163 } 164 // Complete constructor for double constant SPIRVConstantBase(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId,double TheValue)165 SPIRVConstantBase(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId, double TheValue) 166 :SPIRVValue(M, 0, OC, TheType, TheId){ 167 Union.DoubleVal = TheValue; 168 recalculateWordCount(); 169 validate(); 170 } 171 // Incomplete constructor SPIRVConstantBase()172 SPIRVConstantBase():SPIRVValue(OC), NumWords(0){} getZExtIntValue()173 uint64_t getZExtIntValue() const { return Union.UInt64Val;} getFloatValue()174 float getFloatValue() const { return Union.FloatVal;} getDoubleValue()175 double getDoubleValue() const { return Union.DoubleVal;} isConstant()176 bool isConstant() { return true; } 177 protected: recalculateWordCount()178 void recalculateWordCount() { 179 NumWords = (Type->getBitWidth() + 31) / 32; 180 WordCount = 3 + NumWords; 181 } validate()182 void validate() const { 183 SPIRVValue::validate(); 184 IGC_ASSERT_EXIT_MESSAGE(1 <= NumWords, "Invalid constant size"); 185 IGC_ASSERT_EXIT_MESSAGE(NumWords <= 32, "Invalid constant size"); 186 } setWordCount(SPIRVWord WordCount)187 void setWordCount(SPIRVWord WordCount) { 188 SPIRVValue::setWordCount(WordCount); 189 NumWords = WordCount - 3; 190 } decode(std::istream & I)191 void decode(std::istream &I) { 192 getDecoder(I) >> Type >> Id; 193 validate(); 194 for (unsigned i = 0; i < NumWords; ++i) 195 getDecoder(I) >> Union.Words[i]; 196 } 197 198 unsigned NumWords; 199 union UnionType{ 200 uint64_t UInt64Val; 201 float FloatVal; 202 double DoubleVal; 203 SPIRVWord Words[32]; UnionType()204 UnionType() { 205 UInt64Val = 0; 206 } 207 } Union; 208 }; 209 210 typedef SPIRVConstantBase<OpConstant> SPIRVConstant; 211 typedef SPIRVConstantBase<OpSpecConstant> SPIRVSpecConstant; 212 213 template<Op OC> 214 class SPIRVConstantEmpty: public SPIRVValue { 215 public: 216 // Complete constructor SPIRVConstantEmpty(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId)217 SPIRVConstantEmpty(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId) 218 :SPIRVValue(M, 3, OC, TheType, TheId){ 219 validate(); 220 } 221 // Incomplete constructor SPIRVConstantEmpty()222 SPIRVConstantEmpty():SPIRVValue(OC){} 223 protected: validate()224 void validate() const override { 225 SPIRVValue::validate(); 226 } 227 _SPIRV_DEF_DEC2(Type, Id) 228 }; 229 230 template<Op OC> 231 class SPIRVConstantBool: public SPIRVConstantEmpty<OC> { 232 public: 233 // Complete constructor SPIRVConstantBool(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId)234 SPIRVConstantBool(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId) 235 :SPIRVConstantEmpty<OC>(M, TheType, TheId){} 236 // Incomplete constructor SPIRVConstantBool()237 SPIRVConstantBool(){} 238 protected: validate()239 void validate() const { 240 SPIRVConstantEmpty<OC>::validate(); 241 IGC_ASSERT_MESSAGE(this->Type->isTypeBool(), "Invalid type"); 242 } 243 }; 244 245 typedef SPIRVConstantBool<OpConstantTrue> SPIRVConstantTrue; 246 typedef SPIRVConstantBool<OpConstantFalse> SPIRVConstantFalse; 247 248 typedef SPIRVConstantBool<OpSpecConstantTrue> SPIRVSpecConstantTrue; 249 typedef SPIRVConstantBool<OpSpecConstantFalse> SPIRVSpecConstantFalse; 250 251 class SPIRVConstantNull : public SPIRVConstantEmpty<OpConstantNull> 252 { 253 public: 254 // Complete constructor SPIRVConstantNull(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId)255 SPIRVConstantNull(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId) 256 : SPIRVConstantEmpty(M, TheType, TheId) { 257 validate(); 258 } 259 // Incomplete constructor SPIRVConstantNull()260 SPIRVConstantNull() {} 261 protected: validate()262 void validate() const override { 263 SPIRVConstantEmpty::validate(); 264 IGC_ASSERT_MESSAGE((Type->isTypeInt() || Type->isTypeBool() || Type->isTypeFloat() || Type->isTypeComposite() || Type->isTypeOpaque() || Type->isTypeEvent() || Type->isTypePointer() || Type->isTypeReserveId() || Type->isTypeDeviceEvent() || (Type->isTypeSubgroupAvcINTEL())), "Invalid type"); 265 } 266 }; 267 268 class SPIRVUndef : public SPIRVConstantEmpty<OpUndef> 269 { 270 public: 271 // Incomplete constructor SPIRVUndef()272 SPIRVUndef() {} 273 protected: validate()274 void validate() const 275 { 276 SPIRVConstantEmpty::validate(); 277 } 278 }; 279 280 template<Op OC> 281 class SPIRVConstantCompositeBase: public SPIRVValue { 282 public: 283 // There are always 3 words in this instruction except constituents: 284 // 1) WordCount + OpCode 285 // 2) Result type 286 // 3) Result Id 287 constexpr static SPIRVWord FixedWC = 3; 288 using ContinuedInstType = typename InstToContinued<OC>::Type; 289 // Complete constructor for composite constant SPIRVConstantCompositeBase(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId,const std::vector<SPIRVValue * > TheElements)290 SPIRVConstantCompositeBase(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId, 291 const std::vector<SPIRVValue *> TheElements) 292 :SPIRVValue(M, TheElements.size()+ FixedWC, OC, TheType, TheId){ 293 Elements = getIds(TheElements); 294 validate(); 295 } 296 // Incomplete constructor SPIRVConstantCompositeBase()297 SPIRVConstantCompositeBase():SPIRVValue(OC){} getElements()298 std::vector<SPIRVValue*> getElements()const { 299 return getValues(Elements); 300 } 301 getContinuedInstructions()302 std::vector<ContinuedInstType> getContinuedInstructions() { 303 return ContinuedInstructions; 304 } 305 addContinuedInstruction(ContinuedInstType Inst)306 void addContinuedInstruction(ContinuedInstType Inst) { 307 ContinuedInstructions.push_back(Inst); 308 } 309 310 protected: validate()311 void validate() const override { 312 SPIRVValue::validate(); 313 for (auto &I:Elements) 314 getValue(I)->validate(); 315 } setWordCount(SPIRVWord WordCount)316 void setWordCount(SPIRVWord WordCount) override 317 { 318 Elements.resize(WordCount - FixedWC); 319 } 320 decode(std::istream & I)321 void decode(std::istream& I) override 322 { 323 SPIRVDecoder Decoder = getDecoder(I); 324 Decoder >> Type >> Id >> Elements; 325 326 for (SPIRVEntry* E : Decoder.getContinuedInstructions(ContinuedOpCode)) 327 { 328 addContinuedInstruction(static_cast<ContinuedInstType>(E)); 329 } 330 } 331 332 std::vector<SPIRVId> Elements; 333 std::vector<ContinuedInstType> ContinuedInstructions; 334 const igc_spv::Op ContinuedOpCode = InstToContinued<OC>::OpCode; 335 }; 336 337 typedef SPIRVConstantCompositeBase<OpConstantComposite> SPIRVConstantComposite; 338 typedef SPIRVConstantCompositeBase<OpSpecConstantComposite> SPIRVSpecConstantComposite; 339 340 class SPIRVConstantSampler: public SPIRVValue { 341 public: 342 const static Op OC = OpConstantSampler; 343 const static SPIRVWord WC = 6; 344 // Complete constructor SPIRVConstantSampler(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId,SPIRVWord TheAddrMode,SPIRVWord TheNormalized,SPIRVWord TheFilterMode)345 SPIRVConstantSampler(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId, 346 SPIRVWord TheAddrMode, SPIRVWord TheNormalized, SPIRVWord TheFilterMode) 347 :SPIRVValue(M, WC, OC, TheType, TheId), AddrMode(TheAddrMode), 348 Normalized(TheNormalized), FilterMode(TheFilterMode){ 349 validate(); 350 } 351 // Incomplete constructor SPIRVConstantSampler()352 SPIRVConstantSampler() :SPIRVValue(OC), AddrMode(SPIRVSamplerAddressingModeKind::SamplerAddressingModeNone), 353 Normalized(SPIRVWORD_MAX), FilterMode(SPIRVSamplerFilterModeKind::SamplerFilterModeNearest){} 354 getAddrMode()355 SPIRVWord getAddrMode() const { 356 return AddrMode; 357 } 358 getFilterMode()359 SPIRVWord getFilterMode() const { 360 return FilterMode; 361 } 362 getNormalized()363 SPIRVWord getNormalized() const { 364 return Normalized; 365 } getRequiredCapability()366 CapVec getRequiredCapability() const { 367 return getVec(SPIRVCapabilityKind::CapabilityLiteralSampler); 368 } 369 protected: 370 SPIRVWord AddrMode; 371 SPIRVWord Normalized; 372 SPIRVWord FilterMode; validate()373 void validate() const { 374 SPIRVValue::validate(); 375 IGC_ASSERT(OpCode == OC); 376 IGC_ASSERT(WordCount == WC); 377 IGC_ASSERT(Type->isTypeSampler()); 378 } 379 _SPIRV_DEF_DEC5(Type, Id, AddrMode, Normalized, FilterMode) 380 }; 381 382 class SPIRVForward:public SPIRVValue, public SPIRVComponentExecutionModes { 383 public: 384 const static Op OC = OpForward; 385 // Complete constructor SPIRVForward(SPIRVModule * TheModule,SPIRVType * TheTy,SPIRVId TheId)386 SPIRVForward(SPIRVModule *TheModule, SPIRVType *TheTy, SPIRVId TheId): 387 SPIRVValue(TheModule, 0, OC, TheId){ 388 if (TheTy) 389 setType(TheTy); 390 } SPIRVForward()391 SPIRVForward():SPIRVValue(OC) { 392 IGC_ASSERT_EXIT_MESSAGE(0, "should never be called"); 393 } _SPIRV_DEF_DEC1(Id)394 _SPIRV_DEF_DEC1(Id) 395 friend class SPIRVFunction; 396 protected: 397 void validate() const {} 398 }; 399 400 class SPIRVConstantPipeStorage : public SPIRVValue 401 { 402 public: 403 static const Op OC = OpConstantPipeStorage; SPIRVConstantPipeStorage()404 SPIRVConstantPipeStorage() : SPIRVValue(OC) {} GetPacketSize()405 uint32_t GetPacketSize() { return PacketSize; } GetPacketAlignment()406 uint32_t GetPacketAlignment() { return PacketAlignment; } GetCapacity()407 uint32_t GetCapacity() { return Capacity; } 408 private: 409 _SPIRV_DEF_DEC5(Type, Id, PacketSize, PacketAlignment, Capacity) 410 uint32_t PacketSize; 411 uint32_t PacketAlignment; 412 uint32_t Capacity; 413 }; 414 415 } 416 417 418 #endif /* SPIRVVALUE_HPP_ */ 419