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