aboutsummaryrefslogtreecommitdiff
path: root/tools/comp/markv.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/comp/markv.cpp')
-rw-r--r--tools/comp/markv.cpp247
1 files changed, 247 insertions, 0 deletions
diff --git a/tools/comp/markv.cpp b/tools/comp/markv.cpp
new file mode 100644
index 00000000..f9df9ca6
--- /dev/null
+++ b/tools/comp/markv.cpp
@@ -0,0 +1,247 @@
+// Copyright (c) 2017 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <vector>
+
+#include "source/spirv_target_env.h"
+#include "source/table.h"
+#include "spirv-tools/markv.h"
+#include "tools/io.h"
+
+namespace {
+
+enum Task {
+ kNoTask = 0,
+ kEncode,
+ kDecode,
+};
+
+struct ScopedContext {
+ ScopedContext(spv_target_env env) : context(spvContextCreate(env)) {}
+ ~ScopedContext() { spvContextDestroy(context); }
+ spv_context context;
+};
+
+void print_usage(char* argv0) {
+ printf(
+ R"(%s - Encodes or decodes a SPIR-V binary to or from a MARK-V binary.
+
+USAGE: %s [e|d] [options] [<filename>]
+
+The input binary is read from <filename>. If no file is specified,
+or if the filename is "-", then the binary is read from standard input.
+
+If no output is specified then the output is printed to stdout in a human
+readable format.
+
+WIP: MARK-V codec is in early stages of development. At the moment it only
+can encode and decode some SPIR-V files and only if exacly the same build of
+software is used (is doesn't write or handle version numbers yet).
+
+Tasks:
+ e Encode SPIR-V to MARK-V.
+ d Decode MARK-V to SPIR-V.
+
+Options:
+ -h, --help Print this help.
+ --comments Write codec comments to stdout.
+ --version Display MARK-V codec version.
+
+ -o <filename> Set the output filename.
+ Output goes to standard output if this option is
+ not specified, or if the filename is "-".
+)",
+ argv0, argv0);
+}
+
+void DiagnosticsMessageHandler(spv_message_level_t level, const char*,
+ const spv_position_t& position,
+ const char* message) {
+ switch (level) {
+ case SPV_MSG_FATAL:
+ case SPV_MSG_INTERNAL_ERROR:
+ case SPV_MSG_ERROR:
+ std::cerr << "error: " << position.index << ": " << message
+ << std::endl;
+ break;
+ case SPV_MSG_WARNING:
+ std::cout << "warning: " << position.index << ": " << message
+ << std::endl;
+ break;
+ case SPV_MSG_INFO:
+ std::cout << "info: " << position.index << ": " << message << std::endl;
+ break;
+ default:
+ break;
+ }
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ const char* input_filename = nullptr;
+ const char* output_filename = nullptr;
+
+ Task task = kNoTask;
+
+ if (argc < 3) {
+ print_usage(argv[0]);
+ return 0;
+ }
+
+ const char* task_char = argv[1];
+ if (0 == strcmp("e", task_char)) {
+ task = kEncode;
+ } else if (0 == strcmp("d", task_char)) {
+ task = kDecode;
+ }
+
+ if (task == kNoTask) {
+ print_usage(argv[0]);
+ return 1;
+ }
+
+ bool want_comments = false;
+
+ for (int argi = 2; argi < argc; ++argi) {
+ if ('-' == argv[argi][0]) {
+ switch (argv[argi][1]) {
+ case 'h':
+ print_usage(argv[0]);
+ return 0;
+ case 'o': {
+ if (!output_filename && argi + 1 < argc) {
+ output_filename = argv[++argi];
+ } else {
+ print_usage(argv[0]);
+ return 1;
+ }
+ } break;
+ case '-': {
+ if (0 == strcmp(argv[argi], "--help")) {
+ print_usage(argv[0]);
+ return 0;
+ } else if (0 == strcmp(argv[argi], "--comments")) {
+ want_comments = true;
+ } else if (0 == strcmp(argv[argi], "--version")) {
+ fprintf(stderr, "error: Not implemented\n");
+ return 1;
+ } else {
+ print_usage(argv[0]);
+ return 1;
+ }
+ } break;
+ case '\0': {
+ // Setting a filename of "-" to indicate stdin.
+ if (!input_filename) {
+ input_filename = argv[argi];
+ } else {
+ fprintf(stderr, "error: More than one input file specified\n");
+ return 1;
+ }
+ } break;
+ default:
+ print_usage(argv[0]);
+ return 1;
+ }
+ } else {
+ if (!input_filename) {
+ input_filename = argv[argi];
+ } else {
+ fprintf(stderr, "error: More than one input file specified\n");
+ return 1;
+ }
+ }
+ }
+
+ if (task == kDecode && want_comments) {
+ fprintf(stderr, "warning: Decoder comments not yet implemented\n");
+ want_comments = false;
+ }
+
+ const bool write_to_stdout = output_filename == nullptr ||
+ 0 == strcmp(output_filename, "-");
+
+ spv_text comments = nullptr;
+ spv_text* comments_ptr = want_comments ? &comments : nullptr;
+
+ ScopedContext ctx(SPV_ENV_UNIVERSAL_1_2);
+ SetContextMessageConsumer(ctx.context, DiagnosticsMessageHandler);
+
+ if (task == kEncode) {
+ std::vector<uint32_t> contents;
+ if (!ReadFile<uint32_t>(input_filename, "rb", &contents)) return 1;
+
+ std::unique_ptr<spv_markv_encoder_options_t,
+ std::function<void(spv_markv_encoder_options_t*)>> options(
+ spvMarkvEncoderOptionsCreate(), &spvMarkvEncoderOptionsDestroy);
+ spv_markv_binary markv_binary = nullptr;
+
+ if (SPV_SUCCESS !=
+ spvSpirvToMarkv(ctx.context, contents.data(), contents.size(),
+ options.get(), &markv_binary, comments_ptr, nullptr)) {
+ std::cerr << "error: Failed to encode " << input_filename << " to MARK-V "
+ << std::endl;
+ return 1;
+ }
+
+ if (want_comments) {
+ if (!WriteFile<char>(nullptr, "w", comments->str,
+ comments->length)) return 1;
+ }
+
+ if (!want_comments || !write_to_stdout) {
+ if (!WriteFile<uint8_t>(output_filename, "wb", markv_binary->data,
+ markv_binary->length)) return 1;
+ }
+ } else if (task == kDecode) {
+ std::vector<uint8_t> contents;
+ if (!ReadFile<uint8_t>(input_filename, "rb", &contents)) return 1;
+
+ std::unique_ptr<spv_markv_decoder_options_t,
+ std::function<void(spv_markv_decoder_options_t*)>> options(
+ spvMarkvDecoderOptionsCreate(), &spvMarkvDecoderOptionsDestroy);
+ spv_binary spirv_binary = nullptr;
+
+ if (SPV_SUCCESS !=
+ spvMarkvToSpirv(ctx.context, contents.data(), contents.size(),
+ options.get(), &spirv_binary, comments_ptr, nullptr)) {
+ std::cerr << "error: Failed to encode " << input_filename << " to MARK-V "
+ << std::endl;
+ return 1;
+ }
+
+ if (want_comments) {
+ if (!WriteFile<char>(nullptr, "w", comments->str,
+ comments->length)) return 1;
+ }
+
+ if (!want_comments || !write_to_stdout) {
+ if (!WriteFile<uint32_t>(output_filename, "wb", spirv_binary->code,
+ spirv_binary->wordCount)) return 1;
+ }
+ } else {
+ assert(false && "Unknown task");
+ }
+
+ spvTextDestroy(comments);
+
+ return 0;
+}