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