| /* |
| * 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 "Builtin.h" |
| #include "Context.h" |
| #include "GlobalAllocPass.h" |
| #include "GlobalAllocSPIRITPass.h" |
| #include "GlobalMergePass.h" |
| #include "InlinePreparationPass.h" |
| #include "RemoveNonkernelsPass.h" |
| #include "SPIRVModule.h" |
| #include "Wrapper.h" |
| #include "bcinfo/MetadataExtractor.h" |
| #include "pass_queue.h" |
| |
| #include "llvm/ADT/Triple.h" |
| #include "llvm/IR/LegacyPassManager.h" |
| #include "llvm/IR/Module.h" |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/SPIRV.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include "llvm/Transforms/IPO.h" |
| #include "llvm/Transforms/Scalar.h" |
| |
| #define DEBUG_TYPE "rs2spirv-writer" |
| |
| using namespace llvm; |
| using namespace SPIRV; |
| |
| namespace rs2spirv { |
| |
| void addPassesForRS2SPIRV(llvm::legacy::PassManager &PassMgr) { |
| PassMgr.add(createGlobalMergePass()); |
| |
| PassMgr.add(createInlinePreparationPass()); |
| PassMgr.add(createAlwaysInlinerPass()); |
| PassMgr.add(createRemoveNonkernelsPass()); |
| // Delete unreachable globals. |
| PassMgr.add(createGlobalDCEPass()); |
| // Remove dead debug info. |
| PassMgr.add(createStripDeadDebugInfoPass()); |
| // Remove dead func decls. |
| PassMgr.add(createStripDeadPrototypesPass()); |
| // Transform global allocations and accessors (rs[GS]etElementAt) |
| PassMgr.add(createGlobalAllocPass()); |
| // Removed dead MemCpys in 64-bit targets after global alloc pass |
| PassMgr.add(createDeadStoreEliminationPass()); |
| PassMgr.add(createAggressiveDCEPass()); |
| // Delete unreachable globals (after removing global allocations) |
| PassMgr.add(createRemoveAllGlobalAllocPass()); |
| PassMgr.add(createPromoteMemoryToRegisterPass()); |
| PassMgr.add(createTransOCLMD()); |
| // TODO: investigate removal of OCLTypeToSPIRV pass. |
| PassMgr.add(createOCLTypeToSPIRV()); |
| PassMgr.add(createSPIRVRegularizeLLVM()); |
| PassMgr.add(createSPIRVLowerConstExpr()); |
| PassMgr.add(createSPIRVLowerBool()); |
| } |
| |
| bool WriteSPIRV(Context &Ctxt, Module *M, |
| llvm::raw_ostream &OS, std::string &ErrMsg) { |
| llvm::legacy::PassManager PassMgr; |
| addPassesForRS2SPIRV(PassMgr); |
| |
| std::unique_ptr<SPIRVModule> BM(SPIRVModule::createSPIRVModule()); |
| |
| PassMgr.add(createLLVMToSPIRV(BM.get())); |
| PassMgr.run(*M); |
| DEBUG(M->dump()); |
| |
| if (BM->getError(ErrMsg) != SPIRVEC_Success) { |
| return false; |
| } |
| |
| llvm::SmallString<4096> O; |
| llvm::raw_svector_ostream SVOS(O); |
| |
| SVOS << *BM; |
| |
| llvm::StringRef str = SVOS.str(); |
| std::vector<uint32_t> words(str.size() / 4); |
| |
| memcpy(words.data(), str.data(), str.size()); |
| |
| android::spirit::PassQueue spiritPasses; |
| spiritPasses.append(CreateWrapperPass(*M)); |
| spiritPasses.append(CreateBuiltinPass()); |
| spiritPasses.append(CreateGAPass()); |
| |
| int error; |
| auto wordsOut = spiritPasses.run(words, &error); |
| |
| if (error != 0) { |
| OS << *BM; |
| ErrMsg = "Failed to generate wrappers for kernels"; |
| return false; |
| } |
| |
| OS.write(reinterpret_cast<const char *>(wordsOut.data()), |
| wordsOut.size() * 4); |
| |
| return true; |
| } |
| |
| } // namespace rs2spirv |