• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/LegacyPassManager.h"
23 #include "llvm/IR/LLVMContext.h"
24 #include "llvm/IR/Module.h"
25 #include "llvm/Support/CommandLine.h"
26 #include "llvm/Support/DataStream.h"
27 #include "llvm/Support/Debug.h"
28 #include "llvm/Support/FileSystem.h"
29 #include "llvm/Support/PrettyStackTrace.h"
30 #include "llvm/Support/Signals.h"
31 #include "llvm/Support/ToolOutputFile.h"
32 #include "llvm/Support/raw_ostream.h"
33 
34 #include "Context.h"
35 #include "GlobalMergePass.h"
36 #include "RSSPIRVWriter.h"
37 
38 #define DEBUG_TYPE "rs2spirv"
39 
40 namespace kExt {
41 const char SPIRVBinary[] = ".spv";
42 } // namespace kExt
43 
44 using namespace llvm;
45 
46 static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
47                                       cl::init("-"));
48 
49 static cl::opt<std::string> OutputFile("o",
50                                        cl::desc("Override output filename"),
51                                        cl::value_desc("filename"));
52 
53 static cl::opt<std::string> OutputBitcodeFile("bc",
54                                               cl::desc("Override output bitcode filename"),
55                                               cl::value_desc("bitcode filename"));
56 
removeExt(const std::string & FileName)57 static std::string removeExt(const std::string &FileName) {
58   size_t Pos = FileName.find_last_of(".");
59   if (Pos != std::string::npos)
60     return FileName.substr(0, Pos);
61   return FileName;
62 }
63 
WriteBitcode(rs2spirv::Context & Ctxt,Module * M,raw_ostream & OS,std::string & ErrMsg)64 static bool WriteBitcode(rs2spirv::Context &Ctxt, Module *M,
65                          raw_ostream &OS, std::string &ErrMsg) {
66   llvm::legacy::PassManager PassMgr;
67   PassMgr.add(rs2spirv::createGlobalMergePass(true));
68   PassMgr.run(*M);
69 
70   WriteBitcodeToFile(M, OS);
71 
72   return true;
73 }
74 
convertLLVMToSPIRV()75 static int convertLLVMToSPIRV() {
76   LLVMContext Context;
77 
78   std::string Err;
79   auto DS = getDataFileStreamer(InputFile, &Err);
80   if (!DS) {
81     errs() << "Fails to open input file: " << Err;
82     return -1;
83   }
84   ErrorOr<std::unique_ptr<Module>> MOrErr =
85       getStreamedBitcodeModule(InputFile, std::move(DS), Context);
86 
87   if (std::error_code EC = MOrErr.getError()) {
88     errs() << "Fails to load bitcode: " << EC.message();
89     return -1;
90   }
91 
92   std::unique_ptr<Module> M = std::move(*MOrErr);
93 
94   if (std::error_code EC = M->materializeAll()) {
95     errs() << "Fails to materialize: " << EC.message();
96     return -1;
97   }
98 
99   std::error_code EC;
100 
101   std::vector<char> bitcode = android::spirit::readFile<char>(InputFile);
102   std::unique_ptr<bcinfo::MetadataExtractor> ME(
103       new bcinfo::MetadataExtractor(bitcode.data(), bitcode.size()));
104 
105   rs2spirv::Context &Ctxt = rs2spirv::Context::getInstance();
106 
107   if (!Ctxt.Initialize(std::move(ME))) {
108     return -2;
109   }
110 
111   if (!OutputBitcodeFile.empty()) {
112     llvm::StringRef outBCFile(OutputBitcodeFile);
113     llvm::raw_fd_ostream OFS_BC(outBCFile, EC, llvm::sys::fs::F_None);
114     if (!WriteBitcode(Ctxt, M.get(), OFS_BC, Err)) {
115       errs() << "compiler error: " << Err << '\n';
116       return -3;
117     }
118     return 0;
119   }
120 
121   if (OutputFile.empty()) {
122     if (InputFile == "-")
123       OutputFile = "-";
124     else
125       OutputFile = removeExt(InputFile) + kExt::SPIRVBinary;
126   }
127 
128   llvm::StringRef outFile(OutputFile);
129   llvm::raw_fd_ostream OFS(outFile, EC, llvm::sys::fs::F_None);
130 
131   if (!rs2spirv::WriteSPIRV(Ctxt, M.get(), OFS, Err)) {
132     errs() << "compiler error: " << Err << '\n';
133     return -4;
134   }
135 
136   return 0;
137 }
138 
main(int ac,char ** av)139 int main(int ac, char **av) {
140   EnablePrettyStackTrace();
141   sys::PrintStackTraceOnErrorSignal(av[0]);
142   PrettyStackTraceProgram X(ac, av);
143 
144   cl::ParseCommandLineOptions(ac, av, "RenderScript to SPIRV translator");
145 
146   return convertLLVMToSPIRV();
147 }
148