1// Copyright (c) 2016 Google Inc. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and/or associated documentation files (the 5// "Materials"), to deal in the Materials without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Materials, and to 8// permit persons to whom the Materials are furnished to do so, subject to 9// the following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Materials. 13// 14// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS 15// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS 16// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT 17// https://www.khronos.org/registry/ 18// 19// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 26 27#include "libspirv.hpp" 28 29#include "ir_loader.h" 30 31namespace spvtools { 32 33namespace { 34 35// Sets the module header. Meets the interface requirement of spvBinaryParse(). 36spv_result_t SetSpvHeader(void* builder, spv_endianness_t, uint32_t magic, 37 uint32_t version, uint32_t generator, 38 uint32_t id_bound, uint32_t reserved) { 39 reinterpret_cast<ir::IrLoader*>(builder)->SetModuleHeader( 40 magic, version, generator, id_bound, reserved); 41 return SPV_SUCCESS; 42}; 43 44// Processes a parsed instruction. Meets the interface requirement of 45// spvBinaryParse(). 46spv_result_t SetSpvInst(void* builder, const spv_parsed_instruction_t* inst) { 47 reinterpret_cast<ir::IrLoader*>(builder)->AddInstruction(inst); 48 return SPV_SUCCESS; 49}; 50 51} // annoymous namespace 52 53spv_result_t SpvTools::Assemble(const std::string& text, 54 std::vector<uint32_t>* binary) { 55 spv_binary spvbinary = nullptr; 56 spv_diagnostic diagnostic = nullptr; 57 58 spv_result_t status = spvTextToBinary(context_, text.data(), text.size(), 59 &spvbinary, &diagnostic); 60 if (status == SPV_SUCCESS) { 61 binary->assign(spvbinary->code, spvbinary->code + spvbinary->wordCount); 62 } 63 64 spvDiagnosticDestroy(diagnostic); 65 spvBinaryDestroy(spvbinary); 66 67 return status; 68} 69 70spv_result_t SpvTools::Disassemble(const std::vector<uint32_t>& binary, 71 std::string* text) { 72 spv_text spvtext = nullptr; 73 spv_diagnostic diagnostic = nullptr; 74 75 spv_result_t status = spvBinaryToText(context_, binary.data(), binary.size(), 76 SPV_BINARY_TO_TEXT_OPTION_NO_HEADER, 77 &spvtext, &diagnostic); 78 if (status == SPV_SUCCESS) { 79 text->assign(spvtext->str, spvtext->str + spvtext->length); 80 } 81 82 spvDiagnosticDestroy(diagnostic); 83 spvTextDestroy(spvtext); 84 85 return status; 86} 87 88std::unique_ptr<ir::Module> SpvTools::BuildModule( 89 const std::vector<uint32_t>& binary) { 90 spv_diagnostic diagnostic = nullptr; 91 92 std::unique_ptr<ir::Module> module(new ir::Module); 93 ir::IrLoader loader(module.get()); 94 95 spv_result_t status = 96 spvBinaryParse(context_, &loader, binary.data(), binary.size(), 97 SetSpvHeader, SetSpvInst, &diagnostic); 98 99 spvDiagnosticDestroy(diagnostic); 100 101 loader.EndModule(); 102 103 if (status == SPV_SUCCESS) return module; 104 return nullptr; 105} 106 107std::unique_ptr<ir::Module> SpvTools::BuildModule(const std::string& text) { 108 std::vector<uint32_t> binary; 109 if (Assemble(text, &binary) != SPV_SUCCESS) return nullptr; 110 return BuildModule(binary); 111} 112 113} // namespace spvtools 114