1 //===- SPIRVBinaryUtils.cpp - MLIR SPIR-V Binary Module Utilities ---------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines common utilities for SPIR-V binary module. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "mlir/Target/SPIRV/SPIRVBinaryUtils.h" 14 #include "mlir/Dialect/SPIRV/IR/SPIRVTypes.h" 15 #include "llvm/Config/llvm-config.h" // for LLVM_VERSION_MAJOR 16 17 using namespace mlir; 18 19 void spirv::appendModuleHeader(SmallVectorImpl<uint32_t> &header, 20 spirv::Version version, uint32_t idBound) { 21 uint32_t majorVersion = 1; 22 uint32_t minorVersion = 0; 23 switch (version) { 24 #define MIN_VERSION_CASE(v) \ 25 case spirv::Version::V_1_##v: \ 26 minorVersion = v; \ 27 break 28 29 MIN_VERSION_CASE(0); 30 MIN_VERSION_CASE(1); 31 MIN_VERSION_CASE(2); 32 MIN_VERSION_CASE(3); 33 MIN_VERSION_CASE(4); 34 MIN_VERSION_CASE(5); 35 MIN_VERSION_CASE(6); 36 #undef MIN_VERSION_CASE 37 } 38 39 // See "2.3. Physical Layout of a SPIR-V Module and Instruction" in the SPIR-V 40 // spec for the definition of the binary module header. 41 // 42 // The first five words of a SPIR-V module must be: 43 // +-------------------------------------------------------------------------+ 44 // | Magic number | 45 // +-------------------------------------------------------------------------+ 46 // | Version number (bytes: 0 | major number | minor number | 0) | 47 // +-------------------------------------------------------------------------+ 48 // | Generator magic number | 49 // +-------------------------------------------------------------------------+ 50 // | Bound (all result <id>s in the module guaranteed to be less than it) | 51 // +-------------------------------------------------------------------------+ 52 // | 0 (reserved for instruction schema) | 53 // +-------------------------------------------------------------------------+ 54 header.push_back(spirv::kMagicNumber); 55 header.push_back((majorVersion << 16) | (minorVersion << 8)); 56 header.push_back((kGeneratorNumber << 16) | LLVM_VERSION_MAJOR); 57 header.push_back(idBound); // <id> bound 58 header.push_back(0); // Schema (reserved word) 59 } 60 61 /// Returns the word-count-prefixed opcode for an SPIR-V instruction. 62 uint32_t spirv::getPrefixedOpcode(uint32_t wordCount, spirv::Opcode opcode) { 63 assert(((wordCount >> 16) == 0) && "word count out of range!"); 64 return (wordCount << 16) | static_cast<uint32_t>(opcode); 65 } 66 67 void spirv::encodeStringLiteralInto(SmallVectorImpl<uint32_t> &binary, 68 StringRef literal) { 69 // We need to encode the literal and the null termination. 70 auto encodingSize = literal.size() / 4 + 1; 71 auto bufferStartSize = binary.size(); 72 binary.resize(bufferStartSize + encodingSize, 0); 73 std::memcpy(binary.data() + bufferStartSize, literal.data(), literal.size()); 74 } 75