1// Copyright (c) 2015-2016 The Khronos Group 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 <cstdio> 16#include <cstring> 17#include <sstream> 18#include <string> 19#include <vector> 20 21#include "spirv-tools/libspirv.h" 22#include "tools/cfg/bin_to_dot.h" 23#include "tools/io.h" 24#include "tools/util/flags.h" 25 26static const auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_6; 27static const std::string kHelpText = 28 R"(%s - Show the control flow graph in GraphiViz "dot" form. EXPERIMENTAL 29 30Usage: %s [options] [<filename>] 31 32The SPIR-V binary is read from <filename>. If no file is specified, 33or if the filename is "-", then the binary is read from standard input. 34 35Options: 36 37 -h, --help Print this help. 38 --version Display version information. 39 40 -o <filename> Set the output filename. 41 Output goes to standard output if this option is 42 not specified, or if the filename is "-". 43)"; 44 45// clang-format off 46FLAG_SHORT_bool( h, /* default_value= */ false, /* required= */ false); 47FLAG_LONG_bool( help, /* default_value= */ false, /* required= */false); 48FLAG_LONG_bool( version, /* default_value= */ false, /* required= */ false); 49FLAG_SHORT_string(o, /* default_value= */ "", /* required= */ false); 50// clang-format on 51 52int main(int, const char** argv) { 53 if (!flags::Parse(argv)) { 54 return 1; 55 } 56 57 if (flags::h.value() || flags::help.value()) { 58 printf(kHelpText.c_str(), argv[0], argv[0]); 59 return 0; 60 } 61 62 if (flags::version.value()) { 63 printf("%s EXPERIMENTAL\n", spvSoftwareVersionDetailsString()); 64 printf("Target: %s\n", spvTargetEnvDescription(kDefaultEnvironment)); 65 return 0; 66 } 67 68 if (flags::positional_arguments.size() != 1) { 69 fprintf(stderr, "error: exactly one input file must be specified.\n"); 70 return 1; 71 } 72 73 std::string inFile = flags::positional_arguments[0]; 74 std::string outFile = flags::o.value(); 75 76 // Read the input binary. 77 std::vector<uint32_t> contents; 78 if (!ReadBinaryFile<uint32_t>(inFile.c_str(), &contents)) return 1; 79 spv_context context = spvContextCreate(kDefaultEnvironment); 80 spv_diagnostic diagnostic = nullptr; 81 82 std::stringstream ss; 83 auto error = 84 BinaryToDot(context, contents.data(), contents.size(), &ss, &diagnostic); 85 if (error) { 86 spvDiagnosticPrint(diagnostic); 87 spvDiagnosticDestroy(diagnostic); 88 spvContextDestroy(context); 89 return error; 90 } 91 std::string str = ss.str(); 92 WriteFile(outFile.empty() ? nullptr : outFile.c_str(), "w", str.data(), 93 str.size()); 94 95 spvDiagnosticDestroy(diagnostic); 96 spvContextDestroy(context); 97 98 return 0; 99} 100