1 // Copyright (c) 2016 Google Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "spirv-tools/libspirv.hpp" 16 17 #include <iostream> 18 19 #include <string> 20 #include <utility> 21 #include <vector> 22 23 #include "source/table.h" 24 25 namespace spvtools { 26 27 Context::Context(spv_target_env env) : context_(spvContextCreate(env)) {} 28 29 Context::Context(Context&& other) : context_(other.context_) { 30 other.context_ = nullptr; 31 } 32 33 Context& Context::operator=(Context&& other) { 34 spvContextDestroy(context_); 35 context_ = other.context_; 36 other.context_ = nullptr; 37 38 return *this; 39 } 40 41 Context::~Context() { spvContextDestroy(context_); } 42 43 void Context::SetMessageConsumer(MessageConsumer consumer) { 44 SetContextMessageConsumer(context_, std::move(consumer)); 45 } 46 47 spv_context& Context::CContext() { return context_; } 48 49 const spv_context& Context::CContext() const { return context_; } 50 51 // Structs for holding the data members for SpvTools. 52 struct SpirvTools::Impl { 53 explicit Impl(spv_target_env env) : context(spvContextCreate(env)) { 54 // The default consumer in spv_context_t is a null consumer, which provides 55 // equivalent functionality (from the user's perspective) as a real consumer 56 // does nothing. 57 } 58 ~Impl() { spvContextDestroy(context); } 59 60 spv_context context; // C interface context object. 61 }; 62 63 SpirvTools::SpirvTools(spv_target_env env) : impl_(new Impl(env)) {} 64 65 SpirvTools::~SpirvTools() {} 66 67 void SpirvTools::SetMessageConsumer(MessageConsumer consumer) { 68 SetContextMessageConsumer(impl_->context, std::move(consumer)); 69 } 70 71 bool SpirvTools::Assemble(const std::string& text, 72 std::vector<uint32_t>* binary, 73 uint32_t options) const { 74 return Assemble(text.data(), text.size(), binary, options); 75 } 76 77 bool SpirvTools::Assemble(const char* text, const size_t text_size, 78 std::vector<uint32_t>* binary, 79 uint32_t options) const { 80 spv_binary spvbinary = nullptr; 81 spv_result_t status = spvTextToBinaryWithOptions( 82 impl_->context, text, text_size, options, &spvbinary, nullptr); 83 if (status == SPV_SUCCESS) { 84 binary->assign(spvbinary->code, spvbinary->code + spvbinary->wordCount); 85 } 86 spvBinaryDestroy(spvbinary); 87 return status == SPV_SUCCESS; 88 } 89 90 bool SpirvTools::Disassemble(const std::vector<uint32_t>& binary, 91 std::string* text, uint32_t options) const { 92 return Disassemble(binary.data(), binary.size(), text, options); 93 } 94 95 bool SpirvTools::Disassemble(const uint32_t* binary, const size_t binary_size, 96 std::string* text, uint32_t options) const { 97 spv_text spvtext = nullptr; 98 spv_result_t status = spvBinaryToText(impl_->context, binary, binary_size, 99 options, &spvtext, nullptr); 100 if (status == SPV_SUCCESS) { 101 text->assign(spvtext->str, spvtext->str + spvtext->length); 102 } 103 spvTextDestroy(spvtext); 104 return status == SPV_SUCCESS; 105 } 106 107 bool SpirvTools::Validate(const std::vector<uint32_t>& binary) const { 108 return Validate(binary.data(), binary.size()); 109 } 110 111 bool SpirvTools::Validate(const uint32_t* binary, 112 const size_t binary_size) const { 113 return spvValidateBinary(impl_->context, binary, binary_size, nullptr) == 114 SPV_SUCCESS; 115 } 116 117 bool SpirvTools::Validate(const uint32_t* binary, const size_t binary_size, 118 spv_validator_options options) const { 119 spv_const_binary_t the_binary{binary, binary_size}; 120 spv_diagnostic diagnostic = nullptr; 121 bool valid = spvValidateWithOptions(impl_->context, options, &the_binary, 122 &diagnostic) == SPV_SUCCESS; 123 if (!valid && impl_->context->consumer) { 124 impl_->context->consumer.operator()( 125 SPV_MSG_ERROR, nullptr, diagnostic->position, diagnostic->error); 126 } 127 spvDiagnosticDestroy(diagnostic); 128 return valid; 129 } 130 131 } // namespace spvtools 132