1 /*
2 * Copyright 2016, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "RSSPIRVWriter.h"
18 #include "bcinfo/MetadataExtractor.h"
19 #include "spirit/file_utils.h"
20
21 #include "llvm/Bitcode/ReaderWriter.h"
22 #include "llvm/IR/LLVMContext.h"
23 #include "llvm/IR/Module.h"
24 #include "llvm/Support/CommandLine.h"
25 #include "llvm/Support/DataStream.h"
26 #include "llvm/Support/Debug.h"
27 #include "llvm/Support/FileSystem.h"
28 #include "llvm/Support/PrettyStackTrace.h"
29 #include "llvm/Support/Signals.h"
30 #include "llvm/Support/ToolOutputFile.h"
31 #include "llvm/Support/raw_ostream.h"
32
33 #define DEBUG_TYPE "rs2spirv"
34
35 namespace kExt {
36 const char SPIRVBinary[] = ".spv";
37 } // namespace kExt
38
39 using namespace llvm;
40
41 static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
42 cl::init("-"));
43
44 static cl::opt<std::string> OutputFile("o",
45 cl::desc("Override output filename"),
46 cl::value_desc("filename"));
47
removeExt(const std::string & FileName)48 static std::string removeExt(const std::string &FileName) {
49 size_t Pos = FileName.find_last_of(".");
50 if (Pos != std::string::npos)
51 return FileName.substr(0, Pos);
52 return FileName;
53 }
54
convertLLVMToSPIRV()55 static int convertLLVMToSPIRV() {
56 LLVMContext Context;
57
58 std::string Err;
59 auto DS = getDataFileStreamer(InputFile, &Err);
60 if (!DS) {
61 errs() << "Fails to open input file: " << Err;
62 return -1;
63 }
64 ErrorOr<std::unique_ptr<Module>> MOrErr =
65 getStreamedBitcodeModule(InputFile, std::move(DS), Context);
66
67 if (std::error_code EC = MOrErr.getError()) {
68 errs() << "Fails to load bitcode: " << EC.message();
69 return -1;
70 }
71
72 std::unique_ptr<Module> M = std::move(*MOrErr);
73
74 if (std::error_code EC = M->materializeAll()) {
75 errs() << "Fails to materialize: " << EC.message();
76 return -1;
77 }
78
79 if (OutputFile.empty()) {
80 if (InputFile == "-")
81 OutputFile = "-";
82 else
83 OutputFile = removeExt(InputFile) + kExt::SPIRVBinary;
84 }
85
86 llvm::StringRef outFile(OutputFile);
87 std::error_code EC;
88 llvm::raw_fd_ostream OFS(outFile, EC, llvm::sys::fs::F_None);
89
90 std::vector<char> bitcode = android::spirit::readFile<char>(InputFile);
91 std::unique_ptr<bcinfo::MetadataExtractor> ME(
92 new bcinfo::MetadataExtractor(bitcode.data(), bitcode.size()));
93
94 if (!rs2spirv::WriteSPIRV(M.get(), std::move(ME), OFS, Err)) {
95 errs() << "compiler error: " << Err << '\n';
96 return -1;
97 }
98
99 return 0;
100 }
101
main(int ac,char ** av)102 int main(int ac, char **av) {
103 EnablePrettyStackTrace();
104 sys::PrintStackTraceOnErrorSignal(av[0]);
105 PrettyStackTraceProgram X(ac, av);
106
107 cl::ParseCommandLineOptions(ac, av, "RenderScript to SPIRV translator");
108
109 return convertLLVMToSPIRV();
110 }
111