88 lines · cpp
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-exception6//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 "llvm/Config/llvm-config.h" // for LLVM_VERSION_MAJOR15#include "llvm/Support/Debug.h"16 17#define DEBUG_TYPE "spirv-binary-utils"18 19using namespace mlir;20 21void spirv::appendModuleHeader(SmallVectorImpl<uint32_t> &header,22 spirv::Version version, uint32_t idBound) {23 uint32_t majorVersion = 1;24 uint32_t minorVersion = 0;25 switch (version) {26#define MIN_VERSION_CASE(v) \27 case spirv::Version::V_1_##v: \28 minorVersion = v; \29 break30 31 MIN_VERSION_CASE(0);32 MIN_VERSION_CASE(1);33 MIN_VERSION_CASE(2);34 MIN_VERSION_CASE(3);35 MIN_VERSION_CASE(4);36 MIN_VERSION_CASE(5);37 MIN_VERSION_CASE(6);38#undef MIN_VERSION_CASE39 }40 41 // See "2.3. Physical Layout of a SPIR-V Module and Instruction" in the SPIR-V42 // spec for the definition of the binary module header.43 //44 // The first five words of a SPIR-V module must be:45 // +-------------------------------------------------------------------------+46 // | Magic number |47 // +-------------------------------------------------------------------------+48 // | Version number (bytes: 0 | major number | minor number | 0) |49 // +-------------------------------------------------------------------------+50 // | Generator magic number |51 // +-------------------------------------------------------------------------+52 // | Bound (all result <id>s in the module guaranteed to be less than it) |53 // +-------------------------------------------------------------------------+54 // | 0 (reserved for instruction schema) |55 // +-------------------------------------------------------------------------+56 header.push_back(spirv::kMagicNumber);57 header.push_back((majorVersion << 16) | (minorVersion << 8));58 header.push_back((kGeneratorNumber << 16) | LLVM_VERSION_MAJOR);59 header.push_back(idBound); // <id> bound60 header.push_back(0); // Schema (reserved word)61}62 63/// Returns the word-count-prefixed opcode for an SPIR-V instruction.64uint32_t spirv::getPrefixedOpcode(uint32_t wordCount, spirv::Opcode opcode) {65 assert(((wordCount >> 16) == 0) && "word count out of range!");66 return (wordCount << 16) | static_cast<uint32_t>(opcode);67}68 69void spirv::encodeStringLiteralInto(SmallVectorImpl<uint32_t> &binary,70 StringRef literal) {71 // We need to encode the literal and the null termination.72 size_t encodingSize = literal.size() / 4 + 1;73 size_t sizeOfDataToCopy = literal.size();74 if (encodingSize >= kMaxLiteralWordCount) {75 // Reserve one word for the null termination.76 encodingSize = kMaxLiteralWordCount - 1;77 // Do not override the last word (null termination) when copying.78 sizeOfDataToCopy = (encodingSize - 1) * 4;79 LLVM_DEBUG(llvm::dbgs()80 << "Truncating string literal to max size ("81 << (kMaxLiteralWordCount - 1) << "): " << literal << "\n");82 }83 size_t bufferStartSize = binary.size();84 binary.resize(bufferStartSize + encodingSize, 0);85 std::memcpy(binary.data() + bufferStartSize, literal.data(),86 sizeOfDataToCopy);87}88