| /* |
| * Copyright 2016, The Android Open Source Project |
| * |
| * 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 "RSSPIRVWriter.h" |
| #include "bcinfo/MetadataExtractor.h" |
| #include "spirit/file_utils.h" |
| |
| #include "llvm/Bitcode/ReaderWriter.h" |
| #include "llvm/IR/LegacyPassManager.h" |
| #include "llvm/IR/LLVMContext.h" |
| #include "llvm/IR/Module.h" |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/Support/DataStream.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/FileSystem.h" |
| #include "llvm/Support/PrettyStackTrace.h" |
| #include "llvm/Support/Signals.h" |
| #include "llvm/Support/ToolOutputFile.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| #include "Context.h" |
| #include "GlobalMergePass.h" |
| #include "RSSPIRVWriter.h" |
| |
| #define DEBUG_TYPE "rs2spirv" |
| |
| namespace kExt { |
| const char SPIRVBinary[] = ".spv"; |
| } // namespace kExt |
| |
| using namespace llvm; |
| |
| static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"), |
| cl::init("-")); |
| |
| static cl::opt<std::string> OutputFile("o", |
| cl::desc("Override output filename"), |
| cl::value_desc("filename")); |
| |
| static cl::opt<std::string> OutputBitcodeFile("bc", |
| cl::desc("Override output bitcode filename"), |
| cl::value_desc("bitcode filename")); |
| |
| static std::string removeExt(const std::string &FileName) { |
| size_t Pos = FileName.find_last_of("."); |
| if (Pos != std::string::npos) |
| return FileName.substr(0, Pos); |
| return FileName; |
| } |
| |
| static bool WriteBitcode(rs2spirv::Context &Ctxt, Module *M, |
| raw_ostream &OS, std::string &ErrMsg) { |
| llvm::legacy::PassManager PassMgr; |
| PassMgr.add(rs2spirv::createGlobalMergePass(true)); |
| PassMgr.run(*M); |
| |
| WriteBitcodeToFile(M, OS); |
| |
| return true; |
| } |
| |
| static int convertLLVMToSPIRV() { |
| LLVMContext Context; |
| |
| std::string Err; |
| auto DS = getDataFileStreamer(InputFile, &Err); |
| if (!DS) { |
| errs() << "Fails to open input file: " << Err; |
| return -1; |
| } |
| ErrorOr<std::unique_ptr<Module>> MOrErr = |
| getStreamedBitcodeModule(InputFile, std::move(DS), Context); |
| |
| if (std::error_code EC = MOrErr.getError()) { |
| errs() << "Fails to load bitcode: " << EC.message(); |
| return -1; |
| } |
| |
| std::unique_ptr<Module> M = std::move(*MOrErr); |
| |
| if (std::error_code EC = M->materializeAll()) { |
| errs() << "Fails to materialize: " << EC.message(); |
| return -1; |
| } |
| |
| std::error_code EC; |
| |
| std::vector<char> bitcode = android::spirit::readFile<char>(InputFile); |
| std::unique_ptr<bcinfo::MetadataExtractor> ME( |
| new bcinfo::MetadataExtractor(bitcode.data(), bitcode.size())); |
| |
| rs2spirv::Context &Ctxt = rs2spirv::Context::getInstance(); |
| |
| if (!Ctxt.Initialize(std::move(ME))) { |
| return -2; |
| } |
| |
| if (!OutputBitcodeFile.empty()) { |
| llvm::StringRef outBCFile(OutputBitcodeFile); |
| llvm::raw_fd_ostream OFS_BC(outBCFile, EC, llvm::sys::fs::F_None); |
| if (!WriteBitcode(Ctxt, M.get(), OFS_BC, Err)) { |
| errs() << "compiler error: " << Err << '\n'; |
| return -3; |
| } |
| return 0; |
| } |
| |
| if (OutputFile.empty()) { |
| if (InputFile == "-") |
| OutputFile = "-"; |
| else |
| OutputFile = removeExt(InputFile) + kExt::SPIRVBinary; |
| } |
| |
| llvm::StringRef outFile(OutputFile); |
| llvm::raw_fd_ostream OFS(outFile, EC, llvm::sys::fs::F_None); |
| |
| if (!rs2spirv::WriteSPIRV(Ctxt, M.get(), OFS, Err)) { |
| errs() << "compiler error: " << Err << '\n'; |
| return -4; |
| } |
| |
| return 0; |
| } |
| |
| int main(int ac, char **av) { |
| EnablePrettyStackTrace(); |
| sys::PrintStackTraceOnErrorSignal(av[0]); |
| PrettyStackTraceProgram X(ac, av); |
| |
| cl::ParseCommandLineOptions(ac, av, "RenderScript to SPIRV translator"); |
| |
| return convertLLVMToSPIRV(); |
| } |