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