xref: /aosp_15_r20/external/swiftshader/third_party/SPIRV-Tools/tools/as/as.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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 <cassert>
16 #include <cstdio>
17 #include <cstring>
18 #include <vector>
19 
20 #include "source/spirv_target_env.h"
21 #include "spirv-tools/libspirv.h"
22 #include "tools/io.h"
23 #include "tools/util/flags.h"
24 
25 static const auto kDefaultEnvironment = "spv1.6";
26 static const std::string kHelpText =
27     R"(%s - Create a SPIR-V binary module from SPIR-V assembly text
28 
29 Usage: %s [options] [<filename>]
30 
31 The SPIR-V assembly text is read from <filename>.  If no file is specified,
32 or if the filename is "-", then the assembly text is read from standard input.
33 The SPIR-V binary module is written to file "out.spv", unless the -o option
34 is used.
35 
36 Options:
37 
38   -h, --help      Print this help.
39 
40   -o <filename>   Set the output filename. Use '-' to mean stdout.
41   --version       Display assembler version information.
42   --preserve-numeric-ids
43                   Numeric IDs in the binary will have the same values as in the
44                   source. Non-numeric IDs are allocated by filling in the gaps,
45                   starting with 1 and going up.
46   --target-env    %s
47                   Use specified environment.
48 )";
49 
50 // clang-format off
51 FLAG_SHORT_bool(  h,                    /* default_value= */ false,               /* required= */ false);
52 FLAG_LONG_bool(   help,                 /* default_value= */ false,               /* required= */false);
53 FLAG_LONG_bool(   version,              /* default_value= */ false,               /* required= */ false);
54 FLAG_LONG_bool(   preserve_numeric_ids, /* default_value= */ false,               /* required= */ false);
55 FLAG_SHORT_string(o,                    /* default_value= */ "",                  /* required= */ false);
56 FLAG_LONG_string( target_env,           /* default_value= */ kDefaultEnvironment, /* required= */ false);
57 // clang-format on
58 
main(int,const char ** argv)59 int main(int, const char** argv) {
60   if (!flags::Parse(argv)) {
61     return 1;
62   }
63 
64   if (flags::h.value() || flags::help.value()) {
65     const std::string target_env_list = spvTargetEnvList(19, 80);
66     printf(kHelpText.c_str(), argv[0], argv[0], target_env_list.c_str());
67     return 0;
68   }
69 
70   if (flags::version.value()) {
71     spv_target_env target_env;
72     bool success = spvParseTargetEnv(kDefaultEnvironment, &target_env);
73     assert(success && "Default environment should always parse.");
74     if (!success) {
75       fprintf(stderr,
76               "error: invalid default target environment. Please report this "
77               "issue.");
78       return 1;
79     }
80     printf("%s\n", spvSoftwareVersionDetailsString());
81     printf("Target: %s\n", spvTargetEnvDescription(target_env));
82     return 0;
83   }
84 
85   std::string outFile = flags::o.value();
86   if (outFile.empty()) {
87     outFile = "out.spv";
88   }
89 
90   uint32_t options = 0;
91   if (flags::preserve_numeric_ids.value()) {
92     options |= SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS;
93   }
94 
95   spv_target_env target_env;
96   if (!spvParseTargetEnv(flags::target_env.value().c_str(), &target_env)) {
97     fprintf(stderr, "error: Unrecognized target env: %s\n",
98             flags::target_env.value().c_str());
99     return 1;
100   }
101 
102   if (flags::positional_arguments.size() != 1) {
103     fprintf(stderr, "error: exactly one input file must be specified.\n");
104     return 1;
105   }
106   std::string inFile = flags::positional_arguments[0];
107 
108   std::vector<char> contents;
109   if (!ReadTextFile<char>(inFile.c_str(), &contents)) return 1;
110 
111   spv_binary binary;
112   spv_diagnostic diagnostic = nullptr;
113   spv_context context = spvContextCreate(target_env);
114   spv_result_t error = spvTextToBinaryWithOptions(
115       context, contents.data(), contents.size(), options, &binary, &diagnostic);
116   spvContextDestroy(context);
117   if (error) {
118     spvDiagnosticPrint(diagnostic);
119     spvDiagnosticDestroy(diagnostic);
120     return error;
121   }
122 
123   if (!WriteFile<uint32_t>(outFile.c_str(), "wb", binary->code,
124                            binary->wordCount)) {
125     spvBinaryDestroy(binary);
126     return 1;
127   }
128 
129   spvBinaryDestroy(binary);
130 
131   return 0;
132 }
133