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